unified: initial unified kernel implementation
Summary of what this includes:
initialization:
Copy from nano_init.c, with the following changes:
- the main thread is the continuation of the init thread, but an idle
thread is created as well
- _main() initializes threads in groups and starts the EXE group
- the ready queues are initialized
- the main thread is marked as non-essential once the system init is
done
- a weak main() symbol is provided if the application does not provide a
main() function
scheduler:
Not an exhaustive list, but basically provide primitives for:
- adding/removing a thread to/from a wait queue
- adding/removing a thread to/from the ready queue
- marking thread as ready
- locking/unlocking the scheduler
- instead of locking interrupts
- getting/setting thread priority
- checking what state (coop/preempt) a thread is currenlty running in
- rescheduling threads
- finding what thread is the next to run
- yielding/sleeping/aborting sleep
- finding the current thread
threads:
- Add operationns on threads, such as creating and starting them.
standardized handling of kernel object return codes:
- Kernel objects now cause _Swap() to return the following values:
0 => operation successful
-EAGAIN => operation timed out
-Exxxxx => operation failed for another reason
- The thread's swap_data field can be used to return any additional
information required to complete the operation, such as the actual
result of a successful operation.
timeouts:
- same as nano timeouts, renamed to simply 'timeouts'
- the kernel is still tick-based, but objects take timeout values in
ms for forward compatibility with a tickless kernel.
semaphores:
- Port of the nanokernel semaphores, which have the same basic behaviour
as the microkernel ones. Semaphore groups are not yet implemented.
- These semaphores are enhanced in that they accept an initial count and a
count limit. This allows configuring them as binary semaphores, and also
provisioning them without having to "give" the semaphore multiple times
before using them.
mutexes:
- Straight port of the microkernel mutexes. An init function is added to
allow defining them at runtime.
pipes:
- straight port
timers:
- amalgamation of nano and micro timers, with all functionalities
intact.
events:
- re-implementation, using semaphores and workqueues.
mailboxes:
- straight port
message queues:
- straight port of microkernel FIFOs
memory maps:
- straight port
workqueues:
- Basically, have all APIs follow the k_ naming rule, and use the _timeout
subsystem from the unified kernel directory, and not the _nano_timeout
one.
stacks:
- Port of the nanokernel stacks. They can now have multiple threads
pending on them and threads can wait with a timeout.
LIFOs:
- Straight port of the nanokernel LIFOs.
FIFOs:
- Straight port of the nanokernel FIFOs.
Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
Peter Mitsis <peter.mitsis@windriver.com>
Allan Stephens <allan.stephens@windriver.com>
Benjamin Walsh <benjamin.walsh@windriver.com>
Change-Id: Id3cadb3694484ab2ca467889cfb029be3cd3a7d6
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 18:55:39 -04:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2016 Wind River Systems, Inc.
|
|
|
|
*
|
2017-01-18 17:01:01 -08:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
unified: initial unified kernel implementation
Summary of what this includes:
initialization:
Copy from nano_init.c, with the following changes:
- the main thread is the continuation of the init thread, but an idle
thread is created as well
- _main() initializes threads in groups and starts the EXE group
- the ready queues are initialized
- the main thread is marked as non-essential once the system init is
done
- a weak main() symbol is provided if the application does not provide a
main() function
scheduler:
Not an exhaustive list, but basically provide primitives for:
- adding/removing a thread to/from a wait queue
- adding/removing a thread to/from the ready queue
- marking thread as ready
- locking/unlocking the scheduler
- instead of locking interrupts
- getting/setting thread priority
- checking what state (coop/preempt) a thread is currenlty running in
- rescheduling threads
- finding what thread is the next to run
- yielding/sleeping/aborting sleep
- finding the current thread
threads:
- Add operationns on threads, such as creating and starting them.
standardized handling of kernel object return codes:
- Kernel objects now cause _Swap() to return the following values:
0 => operation successful
-EAGAIN => operation timed out
-Exxxxx => operation failed for another reason
- The thread's swap_data field can be used to return any additional
information required to complete the operation, such as the actual
result of a successful operation.
timeouts:
- same as nano timeouts, renamed to simply 'timeouts'
- the kernel is still tick-based, but objects take timeout values in
ms for forward compatibility with a tickless kernel.
semaphores:
- Port of the nanokernel semaphores, which have the same basic behaviour
as the microkernel ones. Semaphore groups are not yet implemented.
- These semaphores are enhanced in that they accept an initial count and a
count limit. This allows configuring them as binary semaphores, and also
provisioning them without having to "give" the semaphore multiple times
before using them.
mutexes:
- Straight port of the microkernel mutexes. An init function is added to
allow defining them at runtime.
pipes:
- straight port
timers:
- amalgamation of nano and micro timers, with all functionalities
intact.
events:
- re-implementation, using semaphores and workqueues.
mailboxes:
- straight port
message queues:
- straight port of microkernel FIFOs
memory maps:
- straight port
workqueues:
- Basically, have all APIs follow the k_ naming rule, and use the _timeout
subsystem from the unified kernel directory, and not the _nano_timeout
one.
stacks:
- Port of the nanokernel stacks. They can now have multiple threads
pending on them and threads can wait with a timeout.
LIFOs:
- Straight port of the nanokernel LIFOs.
FIFOs:
- Straight port of the nanokernel FIFOs.
Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
Peter Mitsis <peter.mitsis@windriver.com>
Allan Stephens <allan.stephens@windriver.com>
Benjamin Walsh <benjamin.walsh@windriver.com>
Change-Id: Id3cadb3694484ab2ca467889cfb029be3cd3a7d6
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 18:55:39 -04:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Memory pools.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <kernel.h>
|
2016-11-08 10:36:50 -05:00
|
|
|
#include <kernel_structs.h>
|
2016-12-17 13:18:45 -05:00
|
|
|
#include <debug/object_tracing_common.h>
|
2016-10-13 10:31:48 -04:00
|
|
|
#include <ksched.h>
|
unified: initial unified kernel implementation
Summary of what this includes:
initialization:
Copy from nano_init.c, with the following changes:
- the main thread is the continuation of the init thread, but an idle
thread is created as well
- _main() initializes threads in groups and starts the EXE group
- the ready queues are initialized
- the main thread is marked as non-essential once the system init is
done
- a weak main() symbol is provided if the application does not provide a
main() function
scheduler:
Not an exhaustive list, but basically provide primitives for:
- adding/removing a thread to/from a wait queue
- adding/removing a thread to/from the ready queue
- marking thread as ready
- locking/unlocking the scheduler
- instead of locking interrupts
- getting/setting thread priority
- checking what state (coop/preempt) a thread is currenlty running in
- rescheduling threads
- finding what thread is the next to run
- yielding/sleeping/aborting sleep
- finding the current thread
threads:
- Add operationns on threads, such as creating and starting them.
standardized handling of kernel object return codes:
- Kernel objects now cause _Swap() to return the following values:
0 => operation successful
-EAGAIN => operation timed out
-Exxxxx => operation failed for another reason
- The thread's swap_data field can be used to return any additional
information required to complete the operation, such as the actual
result of a successful operation.
timeouts:
- same as nano timeouts, renamed to simply 'timeouts'
- the kernel is still tick-based, but objects take timeout values in
ms for forward compatibility with a tickless kernel.
semaphores:
- Port of the nanokernel semaphores, which have the same basic behaviour
as the microkernel ones. Semaphore groups are not yet implemented.
- These semaphores are enhanced in that they accept an initial count and a
count limit. This allows configuring them as binary semaphores, and also
provisioning them without having to "give" the semaphore multiple times
before using them.
mutexes:
- Straight port of the microkernel mutexes. An init function is added to
allow defining them at runtime.
pipes:
- straight port
timers:
- amalgamation of nano and micro timers, with all functionalities
intact.
events:
- re-implementation, using semaphores and workqueues.
mailboxes:
- straight port
message queues:
- straight port of microkernel FIFOs
memory maps:
- straight port
workqueues:
- Basically, have all APIs follow the k_ naming rule, and use the _timeout
subsystem from the unified kernel directory, and not the _nano_timeout
one.
stacks:
- Port of the nanokernel stacks. They can now have multiple threads
pending on them and threads can wait with a timeout.
LIFOs:
- Straight port of the nanokernel LIFOs.
FIFOs:
- Straight port of the nanokernel FIFOs.
Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
Peter Mitsis <peter.mitsis@windriver.com>
Allan Stephens <allan.stephens@windriver.com>
Benjamin Walsh <benjamin.walsh@windriver.com>
Change-Id: Id3cadb3694484ab2ca467889cfb029be3cd3a7d6
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 18:55:39 -04:00
|
|
|
#include <wait_q.h>
|
2016-09-01 18:14:17 -04:00
|
|
|
#include <init.h>
|
2016-10-13 15:44:48 -05:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
unified: initial unified kernel implementation
Summary of what this includes:
initialization:
Copy from nano_init.c, with the following changes:
- the main thread is the continuation of the init thread, but an idle
thread is created as well
- _main() initializes threads in groups and starts the EXE group
- the ready queues are initialized
- the main thread is marked as non-essential once the system init is
done
- a weak main() symbol is provided if the application does not provide a
main() function
scheduler:
Not an exhaustive list, but basically provide primitives for:
- adding/removing a thread to/from a wait queue
- adding/removing a thread to/from the ready queue
- marking thread as ready
- locking/unlocking the scheduler
- instead of locking interrupts
- getting/setting thread priority
- checking what state (coop/preempt) a thread is currenlty running in
- rescheduling threads
- finding what thread is the next to run
- yielding/sleeping/aborting sleep
- finding the current thread
threads:
- Add operationns on threads, such as creating and starting them.
standardized handling of kernel object return codes:
- Kernel objects now cause _Swap() to return the following values:
0 => operation successful
-EAGAIN => operation timed out
-Exxxxx => operation failed for another reason
- The thread's swap_data field can be used to return any additional
information required to complete the operation, such as the actual
result of a successful operation.
timeouts:
- same as nano timeouts, renamed to simply 'timeouts'
- the kernel is still tick-based, but objects take timeout values in
ms for forward compatibility with a tickless kernel.
semaphores:
- Port of the nanokernel semaphores, which have the same basic behaviour
as the microkernel ones. Semaphore groups are not yet implemented.
- These semaphores are enhanced in that they accept an initial count and a
count limit. This allows configuring them as binary semaphores, and also
provisioning them without having to "give" the semaphore multiple times
before using them.
mutexes:
- Straight port of the microkernel mutexes. An init function is added to
allow defining them at runtime.
pipes:
- straight port
timers:
- amalgamation of nano and micro timers, with all functionalities
intact.
events:
- re-implementation, using semaphores and workqueues.
mailboxes:
- straight port
message queues:
- straight port of microkernel FIFOs
memory maps:
- straight port
workqueues:
- Basically, have all APIs follow the k_ naming rule, and use the _timeout
subsystem from the unified kernel directory, and not the _nano_timeout
one.
stacks:
- Port of the nanokernel stacks. They can now have multiple threads
pending on them and threads can wait with a timeout.
LIFOs:
- Straight port of the nanokernel LIFOs.
FIFOs:
- Straight port of the nanokernel FIFOs.
Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
Peter Mitsis <peter.mitsis@windriver.com>
Allan Stephens <allan.stephens@windriver.com>
Benjamin Walsh <benjamin.walsh@windriver.com>
Change-Id: Id3cadb3694484ab2ca467889cfb029be3cd3a7d6
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 18:55:39 -04:00
|
|
|
|
2016-09-01 18:14:17 -04:00
|
|
|
#define _QUAD_BLOCK_AVAILABLE 0x0F
|
|
|
|
#define _QUAD_BLOCK_ALLOCATED 0x0
|
|
|
|
|
2016-10-19 16:10:46 -05:00
|
|
|
extern struct k_mem_pool _k_mem_pool_list_start[];
|
|
|
|
extern struct k_mem_pool _k_mem_pool_list_end[];
|
|
|
|
|
|
|
|
struct k_mem_pool *_trace_list_k_mem_pool;
|
2016-09-01 18:14:17 -04:00
|
|
|
|
|
|
|
static void init_one_memory_pool(struct k_mem_pool *pool);
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @brief Initialize kernel memory pool subsystem
|
|
|
|
*
|
|
|
|
* Perform any initialization of memory pool that wasn't done at build time.
|
|
|
|
*
|
|
|
|
* @return N/A
|
|
|
|
*/
|
|
|
|
static int init_static_pools(struct device *unused)
|
unified: initial unified kernel implementation
Summary of what this includes:
initialization:
Copy from nano_init.c, with the following changes:
- the main thread is the continuation of the init thread, but an idle
thread is created as well
- _main() initializes threads in groups and starts the EXE group
- the ready queues are initialized
- the main thread is marked as non-essential once the system init is
done
- a weak main() symbol is provided if the application does not provide a
main() function
scheduler:
Not an exhaustive list, but basically provide primitives for:
- adding/removing a thread to/from a wait queue
- adding/removing a thread to/from the ready queue
- marking thread as ready
- locking/unlocking the scheduler
- instead of locking interrupts
- getting/setting thread priority
- checking what state (coop/preempt) a thread is currenlty running in
- rescheduling threads
- finding what thread is the next to run
- yielding/sleeping/aborting sleep
- finding the current thread
threads:
- Add operationns on threads, such as creating and starting them.
standardized handling of kernel object return codes:
- Kernel objects now cause _Swap() to return the following values:
0 => operation successful
-EAGAIN => operation timed out
-Exxxxx => operation failed for another reason
- The thread's swap_data field can be used to return any additional
information required to complete the operation, such as the actual
result of a successful operation.
timeouts:
- same as nano timeouts, renamed to simply 'timeouts'
- the kernel is still tick-based, but objects take timeout values in
ms for forward compatibility with a tickless kernel.
semaphores:
- Port of the nanokernel semaphores, which have the same basic behaviour
as the microkernel ones. Semaphore groups are not yet implemented.
- These semaphores are enhanced in that they accept an initial count and a
count limit. This allows configuring them as binary semaphores, and also
provisioning them without having to "give" the semaphore multiple times
before using them.
mutexes:
- Straight port of the microkernel mutexes. An init function is added to
allow defining them at runtime.
pipes:
- straight port
timers:
- amalgamation of nano and micro timers, with all functionalities
intact.
events:
- re-implementation, using semaphores and workqueues.
mailboxes:
- straight port
message queues:
- straight port of microkernel FIFOs
memory maps:
- straight port
workqueues:
- Basically, have all APIs follow the k_ naming rule, and use the _timeout
subsystem from the unified kernel directory, and not the _nano_timeout
one.
stacks:
- Port of the nanokernel stacks. They can now have multiple threads
pending on them and threads can wait with a timeout.
LIFOs:
- Straight port of the nanokernel LIFOs.
FIFOs:
- Straight port of the nanokernel FIFOs.
Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
Peter Mitsis <peter.mitsis@windriver.com>
Allan Stephens <allan.stephens@windriver.com>
Benjamin Walsh <benjamin.walsh@windriver.com>
Change-Id: Id3cadb3694484ab2ca467889cfb029be3cd3a7d6
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 18:55:39 -04:00
|
|
|
{
|
2016-09-01 18:14:17 -04:00
|
|
|
ARG_UNUSED(unused);
|
|
|
|
struct k_mem_pool *pool;
|
|
|
|
|
|
|
|
/* perform initialization for each memory pool */
|
|
|
|
|
2016-10-19 16:10:46 -05:00
|
|
|
for (pool = _k_mem_pool_list_start;
|
|
|
|
pool < _k_mem_pool_list_end;
|
2016-09-01 18:14:17 -04:00
|
|
|
pool++) {
|
|
|
|
init_one_memory_pool(pool);
|
|
|
|
}
|
|
|
|
return 0;
|
unified: initial unified kernel implementation
Summary of what this includes:
initialization:
Copy from nano_init.c, with the following changes:
- the main thread is the continuation of the init thread, but an idle
thread is created as well
- _main() initializes threads in groups and starts the EXE group
- the ready queues are initialized
- the main thread is marked as non-essential once the system init is
done
- a weak main() symbol is provided if the application does not provide a
main() function
scheduler:
Not an exhaustive list, but basically provide primitives for:
- adding/removing a thread to/from a wait queue
- adding/removing a thread to/from the ready queue
- marking thread as ready
- locking/unlocking the scheduler
- instead of locking interrupts
- getting/setting thread priority
- checking what state (coop/preempt) a thread is currenlty running in
- rescheduling threads
- finding what thread is the next to run
- yielding/sleeping/aborting sleep
- finding the current thread
threads:
- Add operationns on threads, such as creating and starting them.
standardized handling of kernel object return codes:
- Kernel objects now cause _Swap() to return the following values:
0 => operation successful
-EAGAIN => operation timed out
-Exxxxx => operation failed for another reason
- The thread's swap_data field can be used to return any additional
information required to complete the operation, such as the actual
result of a successful operation.
timeouts:
- same as nano timeouts, renamed to simply 'timeouts'
- the kernel is still tick-based, but objects take timeout values in
ms for forward compatibility with a tickless kernel.
semaphores:
- Port of the nanokernel semaphores, which have the same basic behaviour
as the microkernel ones. Semaphore groups are not yet implemented.
- These semaphores are enhanced in that they accept an initial count and a
count limit. This allows configuring them as binary semaphores, and also
provisioning them without having to "give" the semaphore multiple times
before using them.
mutexes:
- Straight port of the microkernel mutexes. An init function is added to
allow defining them at runtime.
pipes:
- straight port
timers:
- amalgamation of nano and micro timers, with all functionalities
intact.
events:
- re-implementation, using semaphores and workqueues.
mailboxes:
- straight port
message queues:
- straight port of microkernel FIFOs
memory maps:
- straight port
workqueues:
- Basically, have all APIs follow the k_ naming rule, and use the _timeout
subsystem from the unified kernel directory, and not the _nano_timeout
one.
stacks:
- Port of the nanokernel stacks. They can now have multiple threads
pending on them and threads can wait with a timeout.
LIFOs:
- Straight port of the nanokernel LIFOs.
FIFOs:
- Straight port of the nanokernel FIFOs.
Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
Peter Mitsis <peter.mitsis@windriver.com>
Allan Stephens <allan.stephens@windriver.com>
Benjamin Walsh <benjamin.walsh@windriver.com>
Change-Id: Id3cadb3694484ab2ca467889cfb029be3cd3a7d6
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 18:55:39 -04:00
|
|
|
}
|
|
|
|
|
2016-11-08 11:06:55 -08:00
|
|
|
SYS_INIT(init_static_pools, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
|
2016-10-13 15:44:48 -05:00
|
|
|
|
2016-09-01 18:14:17 -04:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @brief Initialize the memory pool
|
|
|
|
*
|
|
|
|
* Initialize the internal memory accounting structures of the memory pool
|
|
|
|
*
|
|
|
|
* @param pool memory pool descriptor
|
|
|
|
*
|
|
|
|
* @return N/A
|
|
|
|
*/
|
|
|
|
static void init_one_memory_pool(struct k_mem_pool *pool)
|
unified: initial unified kernel implementation
Summary of what this includes:
initialization:
Copy from nano_init.c, with the following changes:
- the main thread is the continuation of the init thread, but an idle
thread is created as well
- _main() initializes threads in groups and starts the EXE group
- the ready queues are initialized
- the main thread is marked as non-essential once the system init is
done
- a weak main() symbol is provided if the application does not provide a
main() function
scheduler:
Not an exhaustive list, but basically provide primitives for:
- adding/removing a thread to/from a wait queue
- adding/removing a thread to/from the ready queue
- marking thread as ready
- locking/unlocking the scheduler
- instead of locking interrupts
- getting/setting thread priority
- checking what state (coop/preempt) a thread is currenlty running in
- rescheduling threads
- finding what thread is the next to run
- yielding/sleeping/aborting sleep
- finding the current thread
threads:
- Add operationns on threads, such as creating and starting them.
standardized handling of kernel object return codes:
- Kernel objects now cause _Swap() to return the following values:
0 => operation successful
-EAGAIN => operation timed out
-Exxxxx => operation failed for another reason
- The thread's swap_data field can be used to return any additional
information required to complete the operation, such as the actual
result of a successful operation.
timeouts:
- same as nano timeouts, renamed to simply 'timeouts'
- the kernel is still tick-based, but objects take timeout values in
ms for forward compatibility with a tickless kernel.
semaphores:
- Port of the nanokernel semaphores, which have the same basic behaviour
as the microkernel ones. Semaphore groups are not yet implemented.
- These semaphores are enhanced in that they accept an initial count and a
count limit. This allows configuring them as binary semaphores, and also
provisioning them without having to "give" the semaphore multiple times
before using them.
mutexes:
- Straight port of the microkernel mutexes. An init function is added to
allow defining them at runtime.
pipes:
- straight port
timers:
- amalgamation of nano and micro timers, with all functionalities
intact.
events:
- re-implementation, using semaphores and workqueues.
mailboxes:
- straight port
message queues:
- straight port of microkernel FIFOs
memory maps:
- straight port
workqueues:
- Basically, have all APIs follow the k_ naming rule, and use the _timeout
subsystem from the unified kernel directory, and not the _nano_timeout
one.
stacks:
- Port of the nanokernel stacks. They can now have multiple threads
pending on them and threads can wait with a timeout.
LIFOs:
- Straight port of the nanokernel LIFOs.
FIFOs:
- Straight port of the nanokernel FIFOs.
Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
Peter Mitsis <peter.mitsis@windriver.com>
Allan Stephens <allan.stephens@windriver.com>
Benjamin Walsh <benjamin.walsh@windriver.com>
Change-Id: Id3cadb3694484ab2ca467889cfb029be3cd3a7d6
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 18:55:39 -04:00
|
|
|
{
|
2016-09-01 18:14:17 -04:00
|
|
|
/*
|
|
|
|
* mark block set for largest block size
|
|
|
|
* as owning all of the memory pool buffer space
|
|
|
|
*/
|
|
|
|
|
|
|
|
int remaining_blocks = pool->nr_of_maxblocks;
|
|
|
|
int j = 0;
|
|
|
|
char *memptr = pool->bufblock;
|
|
|
|
|
|
|
|
while (remaining_blocks >= 4) {
|
|
|
|
pool->block_set[0].quad_block[j].mem_blocks = memptr;
|
|
|
|
pool->block_set[0].quad_block[j].mem_status =
|
|
|
|
_QUAD_BLOCK_AVAILABLE;
|
|
|
|
j++;
|
|
|
|
remaining_blocks -= 4;
|
|
|
|
memptr +=
|
|
|
|
OCTET_TO_SIZEOFUNIT(pool->block_set[0].block_size)
|
|
|
|
* 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (remaining_blocks != 0) {
|
|
|
|
pool->block_set[0].quad_block[j].mem_blocks = memptr;
|
|
|
|
pool->block_set[0].quad_block[j].mem_status =
|
|
|
|
_QUAD_BLOCK_AVAILABLE >> (4 - remaining_blocks);
|
|
|
|
/* non-existent blocks are marked as unavailable */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* note: all other block sets own no blocks, since their
|
|
|
|
* first quad-block has a NULL memory pointer
|
|
|
|
*/
|
|
|
|
sys_dlist_init(&pool->wait_q);
|
2016-10-19 16:10:46 -05:00
|
|
|
SYS_TRACING_OBJ_INIT(k_mem_pool, pool);
|
2016-09-01 18:14:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @brief Determines which block set corresponds to the specified data size
|
|
|
|
*
|
|
|
|
* Finds the block set with the smallest blocks that can hold the specified
|
|
|
|
* amount of data.
|
|
|
|
*
|
|
|
|
* @return block set index
|
|
|
|
*/
|
2016-12-10 23:25:49 -06:00
|
|
|
static int compute_block_set_index(struct k_mem_pool *pool, size_t data_size)
|
2016-09-01 18:14:17 -04:00
|
|
|
{
|
2016-12-10 23:25:49 -06:00
|
|
|
size_t block_size = pool->min_block_size;
|
2016-09-01 18:14:17 -04:00
|
|
|
int offset = pool->nr_of_block_sets - 1;
|
|
|
|
|
|
|
|
while (data_size > block_size) {
|
|
|
|
block_size *= 4;
|
|
|
|
offset--;
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @brief Return an allocated block to its block set
|
|
|
|
*
|
|
|
|
* @param ptr pointer to start of block
|
|
|
|
* @param pool memory pool descriptor
|
|
|
|
* @param index block set identifier
|
|
|
|
*
|
|
|
|
* @return N/A
|
|
|
|
*/
|
|
|
|
static void free_existing_block(char *ptr, struct k_mem_pool *pool, int index)
|
|
|
|
{
|
|
|
|
struct k_mem_pool_quad_block *quad_block =
|
|
|
|
pool->block_set[index].quad_block;
|
|
|
|
char *block_ptr;
|
2017-04-21 10:55:34 -05:00
|
|
|
u32_t i, j;
|
2016-09-01 18:14:17 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* search block set's quad-blocks until the block is located,
|
|
|
|
* then mark it as unused
|
|
|
|
*
|
|
|
|
* note: block *must* exist, so no need to do array bounds checking
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (i = 0; ; i++) {
|
|
|
|
__ASSERT((i < pool->block_set[index].nr_of_entries) &&
|
|
|
|
(quad_block[i].mem_blocks != NULL),
|
|
|
|
"Attempt to free unallocated memory pool block\n");
|
|
|
|
|
|
|
|
block_ptr = quad_block[i].mem_blocks;
|
|
|
|
for (j = 0; j < 4; j++) {
|
|
|
|
if (ptr == block_ptr) {
|
|
|
|
quad_block[i].mem_status |= (1 << j);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
block_ptr += OCTET_TO_SIZEOFUNIT(
|
|
|
|
pool->block_set[index].block_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @brief Defragment the specified memory pool block sets
|
|
|
|
*
|
|
|
|
* Reassembles any quad-blocks that are entirely unused into larger blocks
|
|
|
|
* (to the extent permitted).
|
|
|
|
*
|
|
|
|
* @param pool memory pool descriptor
|
|
|
|
* @param start_block_set_index index of smallest block set to defragment
|
|
|
|
* @param last_block_set_index index of largest block set to defragment
|
|
|
|
*
|
|
|
|
* @return N/A
|
|
|
|
*/
|
|
|
|
static void defrag(struct k_mem_pool *pool,
|
|
|
|
int start_block_set_index, int last_block_set_index)
|
|
|
|
{
|
2017-04-21 10:55:34 -05:00
|
|
|
u32_t i;
|
|
|
|
u32_t k;
|
2016-12-10 23:25:49 -06:00
|
|
|
int j;
|
2016-09-01 18:14:17 -04:00
|
|
|
struct k_mem_pool_quad_block *quad_block;
|
|
|
|
|
|
|
|
/* process block sets from smallest to largest permitted sizes */
|
|
|
|
|
|
|
|
for (j = start_block_set_index; j > last_block_set_index; j--) {
|
|
|
|
|
|
|
|
quad_block = pool->block_set[j].quad_block;
|
|
|
|
i = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
/* block set is done if no more quad-blocks exist */
|
|
|
|
|
|
|
|
if (quad_block[i].mem_blocks == NULL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reassemble current quad-block, if possible */
|
|
|
|
|
|
|
|
if (quad_block[i].mem_status == _QUAD_BLOCK_AVAILABLE) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* mark the corresponding block in next larger
|
|
|
|
* block set as free
|
|
|
|
*/
|
|
|
|
|
|
|
|
free_existing_block(
|
|
|
|
quad_block[i].mem_blocks, pool, j - 1);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* delete the quad-block from this block set
|
|
|
|
* by replacing it with the last quad-block
|
|
|
|
*
|
|
|
|
* (algorithm works even when the deleted
|
|
|
|
* quad-block is the last quad_block)
|
|
|
|
*/
|
|
|
|
|
|
|
|
k = i;
|
2016-10-14 14:06:11 -05:00
|
|
|
while (((k+1) !=
|
|
|
|
pool->block_set[j].nr_of_entries) &&
|
2016-09-01 18:14:17 -04:00
|
|
|
(quad_block[k + 1].mem_blocks != NULL)) {
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
|
|
|
|
quad_block[i].mem_blocks =
|
|
|
|
quad_block[k].mem_blocks;
|
|
|
|
quad_block[i].mem_status =
|
|
|
|
quad_block[k].mem_status;
|
|
|
|
|
|
|
|
quad_block[k].mem_blocks = NULL;
|
|
|
|
|
|
|
|
/* loop & process replacement quad_block[i] */
|
|
|
|
} else {
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* block set is done if at end of quad-block array */
|
|
|
|
|
|
|
|
} while (i < pool->block_set[j].nr_of_entries);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @brief Allocate block from an existing block set
|
|
|
|
*
|
|
|
|
* @param block_set pointer to block set
|
|
|
|
* @param unused_block_index the index of first unused quad-block
|
|
|
|
* when allocation fails, it is the number of quad
|
|
|
|
* blocks in the block set
|
|
|
|
*
|
|
|
|
* @return pointer to allocated block, or NULL if none available
|
|
|
|
*/
|
|
|
|
static char *get_existing_block(struct k_mem_pool_block_set *block_set,
|
|
|
|
int *unused_block_index)
|
|
|
|
{
|
|
|
|
char *found = NULL;
|
2017-04-21 10:55:34 -05:00
|
|
|
u32_t i = 0;
|
2016-09-01 18:14:17 -04:00
|
|
|
int status;
|
|
|
|
int free_bit;
|
|
|
|
|
|
|
|
do {
|
|
|
|
/* give up if no more quad-blocks exist */
|
|
|
|
|
|
|
|
if (block_set->quad_block[i].mem_blocks == NULL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allocate a block from current quad-block, if possible */
|
|
|
|
|
|
|
|
status = block_set->quad_block[i].mem_status;
|
|
|
|
if (status != _QUAD_BLOCK_ALLOCATED) {
|
|
|
|
/* identify first free block */
|
|
|
|
free_bit = find_lsb_set(status) - 1;
|
|
|
|
|
|
|
|
/* compute address of free block */
|
|
|
|
found = block_set->quad_block[i].mem_blocks +
|
|
|
|
(OCTET_TO_SIZEOFUNIT(free_bit *
|
|
|
|
block_set->block_size));
|
|
|
|
|
|
|
|
/* mark block as unavailable (using XOR to invert) */
|
|
|
|
block_set->quad_block[i].mem_status ^=
|
|
|
|
1 << free_bit;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* move on to next quad-block; give up if at end of array */
|
|
|
|
|
|
|
|
} while (++i < block_set->nr_of_entries);
|
|
|
|
|
|
|
|
*unused_block_index = i;
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @brief Allocate a block, recursively fragmenting larger blocks if necessary
|
|
|
|
*
|
|
|
|
* @param pool memory pool descriptor
|
|
|
|
* @param index index of block set currently being examined
|
|
|
|
* @param start_index index of block set for which allocation is being done
|
|
|
|
*
|
|
|
|
* @return pointer to allocated block, or NULL if none available
|
|
|
|
*/
|
|
|
|
static char *get_block_recursive(struct k_mem_pool *pool,
|
|
|
|
int index, int start_index)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *found, *larger_block;
|
|
|
|
struct k_mem_pool_block_set *fr_table;
|
|
|
|
|
|
|
|
/* give up if we've exhausted the set of maximum size blocks */
|
|
|
|
|
|
|
|
if (index < 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* try allocating a block from the current block set */
|
|
|
|
|
|
|
|
fr_table = pool->block_set;
|
|
|
|
i = 0;
|
|
|
|
|
|
|
|
found = get_existing_block(&(fr_table[index]), &i);
|
|
|
|
if (found != NULL) {
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
2016-11-15 12:33:54 -05:00
|
|
|
#ifdef CONFIG_MEM_POOL_DEFRAG_BEFORE_SPLIT
|
2016-09-01 18:14:17 -04:00
|
|
|
/*
|
|
|
|
* do a partial defragmentation of memory pool & try allocating again
|
|
|
|
* - do this on initial invocation only, not recursive ones
|
|
|
|
* (since there is no benefit in repeating the defrag)
|
|
|
|
* - defrag only the blocks smaller than the desired size,
|
|
|
|
* and only until the size needed is reached
|
|
|
|
*
|
|
|
|
* note: defragging at this time tries to preserve the memory pool's
|
|
|
|
* larger blocks by fragmenting them only when necessary
|
|
|
|
* (i.e. at the cost of doing more frequent auto-defragmentations)
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (index == start_index) {
|
|
|
|
defrag(pool, pool->nr_of_block_sets - 1, start_index);
|
|
|
|
found = get_existing_block(&(fr_table[index]), &i);
|
|
|
|
if (found != NULL) {
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* try allocating a block from the next largest block set */
|
|
|
|
|
|
|
|
larger_block = get_block_recursive(pool, index - 1, start_index);
|
|
|
|
if (larger_block != NULL) {
|
|
|
|
/*
|
|
|
|
* add a new quad-block to the current block set,
|
|
|
|
* then mark one of its 4 blocks as used and return it
|
|
|
|
*
|
|
|
|
* note: "i" was earlier set to indicate the first unused
|
|
|
|
* quad-block entry in the current block set
|
|
|
|
*/
|
|
|
|
|
|
|
|
fr_table[index].quad_block[i].mem_blocks = larger_block;
|
|
|
|
fr_table[index].quad_block[i].mem_status =
|
|
|
|
_QUAD_BLOCK_AVAILABLE & (~0x1);
|
2017-04-10 18:23:39 -04:00
|
|
|
|
2016-09-01 18:14:17 -04:00
|
|
|
return larger_block;
|
|
|
|
}
|
|
|
|
|
2016-11-15 12:33:54 -05:00
|
|
|
#ifdef CONFIG_MEM_POOL_SPLIT_BEFORE_DEFRAG
|
2016-09-01 18:14:17 -04:00
|
|
|
/*
|
|
|
|
* do a partial defragmentation of memory pool & try allocating again
|
|
|
|
* - do this on initial invocation only, not recursive ones
|
|
|
|
* (since there is no benefit in repeating the defrag)
|
|
|
|
* - defrag only the blocks smaller than the desired size,
|
|
|
|
* and only until the size needed is reached
|
|
|
|
*
|
|
|
|
* note: defragging at this time tries to limit the cost of doing
|
|
|
|
* auto-defragmentations by doing them only when necessary
|
|
|
|
* (i.e. at the cost of fragmenting the memory pool's larger blocks)
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (index == start_index) {
|
|
|
|
defrag(pool, pool->nr_of_block_sets - 1, start_index);
|
|
|
|
found = get_existing_block(&(fr_table[index]), &i);
|
|
|
|
if (found != NULL) {
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return NULL; /* can't find (or create) desired block */
|
unified: initial unified kernel implementation
Summary of what this includes:
initialization:
Copy from nano_init.c, with the following changes:
- the main thread is the continuation of the init thread, but an idle
thread is created as well
- _main() initializes threads in groups and starts the EXE group
- the ready queues are initialized
- the main thread is marked as non-essential once the system init is
done
- a weak main() symbol is provided if the application does not provide a
main() function
scheduler:
Not an exhaustive list, but basically provide primitives for:
- adding/removing a thread to/from a wait queue
- adding/removing a thread to/from the ready queue
- marking thread as ready
- locking/unlocking the scheduler
- instead of locking interrupts
- getting/setting thread priority
- checking what state (coop/preempt) a thread is currenlty running in
- rescheduling threads
- finding what thread is the next to run
- yielding/sleeping/aborting sleep
- finding the current thread
threads:
- Add operationns on threads, such as creating and starting them.
standardized handling of kernel object return codes:
- Kernel objects now cause _Swap() to return the following values:
0 => operation successful
-EAGAIN => operation timed out
-Exxxxx => operation failed for another reason
- The thread's swap_data field can be used to return any additional
information required to complete the operation, such as the actual
result of a successful operation.
timeouts:
- same as nano timeouts, renamed to simply 'timeouts'
- the kernel is still tick-based, but objects take timeout values in
ms for forward compatibility with a tickless kernel.
semaphores:
- Port of the nanokernel semaphores, which have the same basic behaviour
as the microkernel ones. Semaphore groups are not yet implemented.
- These semaphores are enhanced in that they accept an initial count and a
count limit. This allows configuring them as binary semaphores, and also
provisioning them without having to "give" the semaphore multiple times
before using them.
mutexes:
- Straight port of the microkernel mutexes. An init function is added to
allow defining them at runtime.
pipes:
- straight port
timers:
- amalgamation of nano and micro timers, with all functionalities
intact.
events:
- re-implementation, using semaphores and workqueues.
mailboxes:
- straight port
message queues:
- straight port of microkernel FIFOs
memory maps:
- straight port
workqueues:
- Basically, have all APIs follow the k_ naming rule, and use the _timeout
subsystem from the unified kernel directory, and not the _nano_timeout
one.
stacks:
- Port of the nanokernel stacks. They can now have multiple threads
pending on them and threads can wait with a timeout.
LIFOs:
- Straight port of the nanokernel LIFOs.
FIFOs:
- Straight port of the nanokernel FIFOs.
Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
Peter Mitsis <peter.mitsis@windriver.com>
Allan Stephens <allan.stephens@windriver.com>
Benjamin Walsh <benjamin.walsh@windriver.com>
Change-Id: Id3cadb3694484ab2ca467889cfb029be3cd3a7d6
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 18:55:39 -04:00
|
|
|
}
|
|
|
|
|
2016-09-01 18:14:17 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @brief Examine threads that are waiting for memory pool blocks.
|
|
|
|
*
|
|
|
|
* This routine attempts to satisfy any incomplete block allocation requests for
|
|
|
|
* the specified memory pool. It can be invoked either by the explicit freeing
|
|
|
|
* of a used block or as a result of defragmenting the pool (which may create
|
|
|
|
* one or more new, larger blocks).
|
|
|
|
*
|
|
|
|
* @return N/A
|
|
|
|
*/
|
|
|
|
static void block_waiters_check(struct k_mem_pool *pool)
|
unified: initial unified kernel implementation
Summary of what this includes:
initialization:
Copy from nano_init.c, with the following changes:
- the main thread is the continuation of the init thread, but an idle
thread is created as well
- _main() initializes threads in groups and starts the EXE group
- the ready queues are initialized
- the main thread is marked as non-essential once the system init is
done
- a weak main() symbol is provided if the application does not provide a
main() function
scheduler:
Not an exhaustive list, but basically provide primitives for:
- adding/removing a thread to/from a wait queue
- adding/removing a thread to/from the ready queue
- marking thread as ready
- locking/unlocking the scheduler
- instead of locking interrupts
- getting/setting thread priority
- checking what state (coop/preempt) a thread is currenlty running in
- rescheduling threads
- finding what thread is the next to run
- yielding/sleeping/aborting sleep
- finding the current thread
threads:
- Add operationns on threads, such as creating and starting them.
standardized handling of kernel object return codes:
- Kernel objects now cause _Swap() to return the following values:
0 => operation successful
-EAGAIN => operation timed out
-Exxxxx => operation failed for another reason
- The thread's swap_data field can be used to return any additional
information required to complete the operation, such as the actual
result of a successful operation.
timeouts:
- same as nano timeouts, renamed to simply 'timeouts'
- the kernel is still tick-based, but objects take timeout values in
ms for forward compatibility with a tickless kernel.
semaphores:
- Port of the nanokernel semaphores, which have the same basic behaviour
as the microkernel ones. Semaphore groups are not yet implemented.
- These semaphores are enhanced in that they accept an initial count and a
count limit. This allows configuring them as binary semaphores, and also
provisioning them without having to "give" the semaphore multiple times
before using them.
mutexes:
- Straight port of the microkernel mutexes. An init function is added to
allow defining them at runtime.
pipes:
- straight port
timers:
- amalgamation of nano and micro timers, with all functionalities
intact.
events:
- re-implementation, using semaphores and workqueues.
mailboxes:
- straight port
message queues:
- straight port of microkernel FIFOs
memory maps:
- straight port
workqueues:
- Basically, have all APIs follow the k_ naming rule, and use the _timeout
subsystem from the unified kernel directory, and not the _nano_timeout
one.
stacks:
- Port of the nanokernel stacks. They can now have multiple threads
pending on them and threads can wait with a timeout.
LIFOs:
- Straight port of the nanokernel LIFOs.
FIFOs:
- Straight port of the nanokernel FIFOs.
Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
Peter Mitsis <peter.mitsis@windriver.com>
Allan Stephens <allan.stephens@windriver.com>
Benjamin Walsh <benjamin.walsh@windriver.com>
Change-Id: Id3cadb3694484ab2ca467889cfb029be3cd3a7d6
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 18:55:39 -04:00
|
|
|
{
|
2016-09-01 18:14:17 -04:00
|
|
|
char *found_block;
|
|
|
|
struct k_thread *waiter;
|
|
|
|
struct k_thread *next_waiter;
|
|
|
|
int offset;
|
|
|
|
|
|
|
|
unsigned int key = irq_lock();
|
|
|
|
waiter = (struct k_thread *)sys_dlist_peek_head(&pool->wait_q);
|
|
|
|
|
|
|
|
/* loop all waiters */
|
|
|
|
while (waiter != NULL) {
|
2017-04-21 10:55:34 -05:00
|
|
|
u32_t req_size = (u32_t)(waiter->base.swap_data);
|
2016-09-01 18:14:17 -04:00
|
|
|
|
|
|
|
/* locate block set to try allocating from */
|
|
|
|
offset = compute_block_set_index(pool, req_size);
|
|
|
|
|
|
|
|
/* allocate block (fragmenting a larger block, if needed) */
|
|
|
|
found_block = get_block_recursive(pool, offset, offset);
|
|
|
|
|
|
|
|
next_waiter = (struct k_thread *)sys_dlist_peek_next(
|
2016-11-08 10:36:50 -05:00
|
|
|
&pool->wait_q, &waiter->base.k_q_node);
|
2016-09-01 18:14:17 -04:00
|
|
|
|
|
|
|
/* if success : remove task from list and reschedule */
|
|
|
|
if (found_block != NULL) {
|
|
|
|
/* return found block */
|
|
|
|
_set_thread_return_value_with_data(waiter, 0,
|
|
|
|
found_block);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Schedule the thread. Threads will be rescheduled
|
|
|
|
* outside the function by k_sched_unlock()
|
|
|
|
*/
|
|
|
|
_unpend_thread(waiter);
|
2016-10-05 12:55:17 -04:00
|
|
|
_abort_thread_timeout(waiter);
|
2016-09-01 18:14:17 -04:00
|
|
|
_ready_thread(waiter);
|
|
|
|
}
|
|
|
|
waiter = next_waiter;
|
|
|
|
}
|
|
|
|
irq_unlock(key);
|
unified: initial unified kernel implementation
Summary of what this includes:
initialization:
Copy from nano_init.c, with the following changes:
- the main thread is the continuation of the init thread, but an idle
thread is created as well
- _main() initializes threads in groups and starts the EXE group
- the ready queues are initialized
- the main thread is marked as non-essential once the system init is
done
- a weak main() symbol is provided if the application does not provide a
main() function
scheduler:
Not an exhaustive list, but basically provide primitives for:
- adding/removing a thread to/from a wait queue
- adding/removing a thread to/from the ready queue
- marking thread as ready
- locking/unlocking the scheduler
- instead of locking interrupts
- getting/setting thread priority
- checking what state (coop/preempt) a thread is currenlty running in
- rescheduling threads
- finding what thread is the next to run
- yielding/sleeping/aborting sleep
- finding the current thread
threads:
- Add operationns on threads, such as creating and starting them.
standardized handling of kernel object return codes:
- Kernel objects now cause _Swap() to return the following values:
0 => operation successful
-EAGAIN => operation timed out
-Exxxxx => operation failed for another reason
- The thread's swap_data field can be used to return any additional
information required to complete the operation, such as the actual
result of a successful operation.
timeouts:
- same as nano timeouts, renamed to simply 'timeouts'
- the kernel is still tick-based, but objects take timeout values in
ms for forward compatibility with a tickless kernel.
semaphores:
- Port of the nanokernel semaphores, which have the same basic behaviour
as the microkernel ones. Semaphore groups are not yet implemented.
- These semaphores are enhanced in that they accept an initial count and a
count limit. This allows configuring them as binary semaphores, and also
provisioning them without having to "give" the semaphore multiple times
before using them.
mutexes:
- Straight port of the microkernel mutexes. An init function is added to
allow defining them at runtime.
pipes:
- straight port
timers:
- amalgamation of nano and micro timers, with all functionalities
intact.
events:
- re-implementation, using semaphores and workqueues.
mailboxes:
- straight port
message queues:
- straight port of microkernel FIFOs
memory maps:
- straight port
workqueues:
- Basically, have all APIs follow the k_ naming rule, and use the _timeout
subsystem from the unified kernel directory, and not the _nano_timeout
one.
stacks:
- Port of the nanokernel stacks. They can now have multiple threads
pending on them and threads can wait with a timeout.
LIFOs:
- Straight port of the nanokernel LIFOs.
FIFOs:
- Straight port of the nanokernel FIFOs.
Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
Peter Mitsis <peter.mitsis@windriver.com>
Allan Stephens <allan.stephens@windriver.com>
Benjamin Walsh <benjamin.walsh@windriver.com>
Change-Id: Id3cadb3694484ab2ca467889cfb029be3cd3a7d6
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 18:55:39 -04:00
|
|
|
}
|
|
|
|
|
2016-09-29 14:07:36 -04:00
|
|
|
void k_mem_pool_defrag(struct k_mem_pool *pool)
|
unified: initial unified kernel implementation
Summary of what this includes:
initialization:
Copy from nano_init.c, with the following changes:
- the main thread is the continuation of the init thread, but an idle
thread is created as well
- _main() initializes threads in groups and starts the EXE group
- the ready queues are initialized
- the main thread is marked as non-essential once the system init is
done
- a weak main() symbol is provided if the application does not provide a
main() function
scheduler:
Not an exhaustive list, but basically provide primitives for:
- adding/removing a thread to/from a wait queue
- adding/removing a thread to/from the ready queue
- marking thread as ready
- locking/unlocking the scheduler
- instead of locking interrupts
- getting/setting thread priority
- checking what state (coop/preempt) a thread is currenlty running in
- rescheduling threads
- finding what thread is the next to run
- yielding/sleeping/aborting sleep
- finding the current thread
threads:
- Add operationns on threads, such as creating and starting them.
standardized handling of kernel object return codes:
- Kernel objects now cause _Swap() to return the following values:
0 => operation successful
-EAGAIN => operation timed out
-Exxxxx => operation failed for another reason
- The thread's swap_data field can be used to return any additional
information required to complete the operation, such as the actual
result of a successful operation.
timeouts:
- same as nano timeouts, renamed to simply 'timeouts'
- the kernel is still tick-based, but objects take timeout values in
ms for forward compatibility with a tickless kernel.
semaphores:
- Port of the nanokernel semaphores, which have the same basic behaviour
as the microkernel ones. Semaphore groups are not yet implemented.
- These semaphores are enhanced in that they accept an initial count and a
count limit. This allows configuring them as binary semaphores, and also
provisioning them without having to "give" the semaphore multiple times
before using them.
mutexes:
- Straight port of the microkernel mutexes. An init function is added to
allow defining them at runtime.
pipes:
- straight port
timers:
- amalgamation of nano and micro timers, with all functionalities
intact.
events:
- re-implementation, using semaphores and workqueues.
mailboxes:
- straight port
message queues:
- straight port of microkernel FIFOs
memory maps:
- straight port
workqueues:
- Basically, have all APIs follow the k_ naming rule, and use the _timeout
subsystem from the unified kernel directory, and not the _nano_timeout
one.
stacks:
- Port of the nanokernel stacks. They can now have multiple threads
pending on them and threads can wait with a timeout.
LIFOs:
- Straight port of the nanokernel LIFOs.
FIFOs:
- Straight port of the nanokernel FIFOs.
Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
Peter Mitsis <peter.mitsis@windriver.com>
Allan Stephens <allan.stephens@windriver.com>
Benjamin Walsh <benjamin.walsh@windriver.com>
Change-Id: Id3cadb3694484ab2ca467889cfb029be3cd3a7d6
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 18:55:39 -04:00
|
|
|
{
|
2016-11-10 14:46:58 -05:00
|
|
|
_sched_lock();
|
2016-09-01 18:14:17 -04:00
|
|
|
|
|
|
|
/* do complete defragmentation of memory pool (i.e. all block sets) */
|
|
|
|
defrag(pool, pool->nr_of_block_sets - 1, 0);
|
|
|
|
|
|
|
|
/* reschedule anybody waiting for a block */
|
|
|
|
block_waiters_check(pool);
|
|
|
|
k_sched_unlock();
|
unified: initial unified kernel implementation
Summary of what this includes:
initialization:
Copy from nano_init.c, with the following changes:
- the main thread is the continuation of the init thread, but an idle
thread is created as well
- _main() initializes threads in groups and starts the EXE group
- the ready queues are initialized
- the main thread is marked as non-essential once the system init is
done
- a weak main() symbol is provided if the application does not provide a
main() function
scheduler:
Not an exhaustive list, but basically provide primitives for:
- adding/removing a thread to/from a wait queue
- adding/removing a thread to/from the ready queue
- marking thread as ready
- locking/unlocking the scheduler
- instead of locking interrupts
- getting/setting thread priority
- checking what state (coop/preempt) a thread is currenlty running in
- rescheduling threads
- finding what thread is the next to run
- yielding/sleeping/aborting sleep
- finding the current thread
threads:
- Add operationns on threads, such as creating and starting them.
standardized handling of kernel object return codes:
- Kernel objects now cause _Swap() to return the following values:
0 => operation successful
-EAGAIN => operation timed out
-Exxxxx => operation failed for another reason
- The thread's swap_data field can be used to return any additional
information required to complete the operation, such as the actual
result of a successful operation.
timeouts:
- same as nano timeouts, renamed to simply 'timeouts'
- the kernel is still tick-based, but objects take timeout values in
ms for forward compatibility with a tickless kernel.
semaphores:
- Port of the nanokernel semaphores, which have the same basic behaviour
as the microkernel ones. Semaphore groups are not yet implemented.
- These semaphores are enhanced in that they accept an initial count and a
count limit. This allows configuring them as binary semaphores, and also
provisioning them without having to "give" the semaphore multiple times
before using them.
mutexes:
- Straight port of the microkernel mutexes. An init function is added to
allow defining them at runtime.
pipes:
- straight port
timers:
- amalgamation of nano and micro timers, with all functionalities
intact.
events:
- re-implementation, using semaphores and workqueues.
mailboxes:
- straight port
message queues:
- straight port of microkernel FIFOs
memory maps:
- straight port
workqueues:
- Basically, have all APIs follow the k_ naming rule, and use the _timeout
subsystem from the unified kernel directory, and not the _nano_timeout
one.
stacks:
- Port of the nanokernel stacks. They can now have multiple threads
pending on them and threads can wait with a timeout.
LIFOs:
- Straight port of the nanokernel LIFOs.
FIFOs:
- Straight port of the nanokernel FIFOs.
Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
Peter Mitsis <peter.mitsis@windriver.com>
Allan Stephens <allan.stephens@windriver.com>
Benjamin Walsh <benjamin.walsh@windriver.com>
Change-Id: Id3cadb3694484ab2ca467889cfb029be3cd3a7d6
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 18:55:39 -04:00
|
|
|
}
|
|
|
|
|
2016-09-29 14:07:36 -04:00
|
|
|
int k_mem_pool_alloc(struct k_mem_pool *pool, struct k_mem_block *block,
|
2017-04-21 10:55:34 -05:00
|
|
|
size_t size, s32_t timeout)
|
2016-09-01 18:14:17 -04:00
|
|
|
{
|
|
|
|
char *found_block;
|
|
|
|
int offset;
|
|
|
|
|
2016-11-10 14:46:58 -05:00
|
|
|
_sched_lock();
|
2016-09-01 18:14:17 -04:00
|
|
|
/* locate block set to try allocating from */
|
|
|
|
offset = compute_block_set_index(pool, size);
|
|
|
|
|
|
|
|
/* allocate block (fragmenting a larger block, if needed) */
|
|
|
|
found_block = get_block_recursive(pool, offset, offset);
|
|
|
|
|
|
|
|
|
|
|
|
if (found_block != NULL) {
|
|
|
|
k_sched_unlock();
|
|
|
|
block->pool_id = pool;
|
|
|
|
block->addr_in_pool = found_block;
|
|
|
|
block->data = found_block;
|
|
|
|
block->req_size = size;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* no suitable block is currently available,
|
|
|
|
* so either wait for one to appear or indicate failure
|
|
|
|
*/
|
2016-10-05 15:15:11 -04:00
|
|
|
if (likely(timeout != K_NO_WAIT)) {
|
2016-09-01 18:14:17 -04:00
|
|
|
int result;
|
|
|
|
unsigned int key = irq_lock();
|
|
|
|
_sched_unlock_no_reschedule();
|
|
|
|
|
2016-11-08 10:36:50 -05:00
|
|
|
_current->base.swap_data = (void *)size;
|
2016-09-01 18:14:17 -04:00
|
|
|
_pend_current_thread(&pool->wait_q, timeout);
|
|
|
|
result = _Swap(key);
|
|
|
|
if (result == 0) {
|
|
|
|
block->pool_id = pool;
|
2016-11-08 10:36:50 -05:00
|
|
|
block->addr_in_pool = _current->base.swap_data;
|
|
|
|
block->data = _current->base.swap_data;
|
2016-09-01 18:14:17 -04:00
|
|
|
block->req_size = size;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
k_sched_unlock();
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2016-10-13 13:18:26 -04:00
|
|
|
void k_mem_pool_free(struct k_mem_block *block)
|
2016-09-01 18:14:17 -04:00
|
|
|
{
|
|
|
|
int offset;
|
2016-10-13 13:18:26 -04:00
|
|
|
struct k_mem_pool *pool = block->pool_id;
|
2016-09-01 18:14:17 -04:00
|
|
|
|
2016-11-10 14:46:58 -05:00
|
|
|
_sched_lock();
|
2016-09-01 18:14:17 -04:00
|
|
|
/* determine block set that block belongs to */
|
2016-10-13 13:18:26 -04:00
|
|
|
offset = compute_block_set_index(pool, block->req_size);
|
2016-09-01 18:14:17 -04:00
|
|
|
|
|
|
|
/* mark the block as unused */
|
2016-10-13 13:18:26 -04:00
|
|
|
free_existing_block(block->addr_in_pool, pool, offset);
|
2016-09-01 18:14:17 -04:00
|
|
|
|
|
|
|
/* reschedule anybody waiting for a block */
|
|
|
|
block_waiters_check(pool);
|
|
|
|
k_sched_unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-13 15:44:48 -05:00
|
|
|
/*
|
|
|
|
* Heap memory pool support
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
|
|
|
|
|
|
|
|
/*
|
2017-04-18 16:42:09 -04:00
|
|
|
* Heap is defined using HEAP_MEM_POOL_SIZE configuration option.
|
2016-10-13 15:44:48 -05:00
|
|
|
*
|
|
|
|
* This module defines the heap memory pool and the _HEAP_MEM_POOL symbol
|
|
|
|
* that has the address of the associated memory pool struct.
|
|
|
|
*/
|
|
|
|
|
|
|
|
K_MEM_POOL_DEFINE(_heap_mem_pool, 64, CONFIG_HEAP_MEM_POOL_SIZE, 1, 4);
|
|
|
|
#define _HEAP_MEM_POOL (&_heap_mem_pool)
|
|
|
|
|
|
|
|
void *k_malloc(size_t size)
|
|
|
|
{
|
|
|
|
struct k_mem_block block;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* get a block large enough to hold an initial (hidden) block
|
|
|
|
* descriptor, as well as the space the caller requested
|
|
|
|
*/
|
|
|
|
size += sizeof(struct k_mem_block);
|
|
|
|
if (k_mem_pool_alloc(_HEAP_MEM_POOL, &block, size, K_NO_WAIT) != 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* save the block descriptor info at the start of the actual block */
|
|
|
|
memcpy(block.data, &block, sizeof(struct k_mem_block));
|
|
|
|
|
|
|
|
/* return address of the user area part of the block to the caller */
|
|
|
|
return (char *)block.data + sizeof(struct k_mem_block);
|
unified: initial unified kernel implementation
Summary of what this includes:
initialization:
Copy from nano_init.c, with the following changes:
- the main thread is the continuation of the init thread, but an idle
thread is created as well
- _main() initializes threads in groups and starts the EXE group
- the ready queues are initialized
- the main thread is marked as non-essential once the system init is
done
- a weak main() symbol is provided if the application does not provide a
main() function
scheduler:
Not an exhaustive list, but basically provide primitives for:
- adding/removing a thread to/from a wait queue
- adding/removing a thread to/from the ready queue
- marking thread as ready
- locking/unlocking the scheduler
- instead of locking interrupts
- getting/setting thread priority
- checking what state (coop/preempt) a thread is currenlty running in
- rescheduling threads
- finding what thread is the next to run
- yielding/sleeping/aborting sleep
- finding the current thread
threads:
- Add operationns on threads, such as creating and starting them.
standardized handling of kernel object return codes:
- Kernel objects now cause _Swap() to return the following values:
0 => operation successful
-EAGAIN => operation timed out
-Exxxxx => operation failed for another reason
- The thread's swap_data field can be used to return any additional
information required to complete the operation, such as the actual
result of a successful operation.
timeouts:
- same as nano timeouts, renamed to simply 'timeouts'
- the kernel is still tick-based, but objects take timeout values in
ms for forward compatibility with a tickless kernel.
semaphores:
- Port of the nanokernel semaphores, which have the same basic behaviour
as the microkernel ones. Semaphore groups are not yet implemented.
- These semaphores are enhanced in that they accept an initial count and a
count limit. This allows configuring them as binary semaphores, and also
provisioning them without having to "give" the semaphore multiple times
before using them.
mutexes:
- Straight port of the microkernel mutexes. An init function is added to
allow defining them at runtime.
pipes:
- straight port
timers:
- amalgamation of nano and micro timers, with all functionalities
intact.
events:
- re-implementation, using semaphores and workqueues.
mailboxes:
- straight port
message queues:
- straight port of microkernel FIFOs
memory maps:
- straight port
workqueues:
- Basically, have all APIs follow the k_ naming rule, and use the _timeout
subsystem from the unified kernel directory, and not the _nano_timeout
one.
stacks:
- Port of the nanokernel stacks. They can now have multiple threads
pending on them and threads can wait with a timeout.
LIFOs:
- Straight port of the nanokernel LIFOs.
FIFOs:
- Straight port of the nanokernel FIFOs.
Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
Peter Mitsis <peter.mitsis@windriver.com>
Allan Stephens <allan.stephens@windriver.com>
Benjamin Walsh <benjamin.walsh@windriver.com>
Change-Id: Id3cadb3694484ab2ca467889cfb029be3cd3a7d6
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 18:55:39 -04:00
|
|
|
}
|
2016-09-01 18:14:17 -04:00
|
|
|
|
2016-10-13 15:44:48 -05:00
|
|
|
|
|
|
|
void k_free(void *ptr)
|
|
|
|
{
|
|
|
|
if (ptr != NULL) {
|
|
|
|
/* point to hidden block descriptor at start of block */
|
|
|
|
ptr = (char *)ptr - sizeof(struct k_mem_block);
|
|
|
|
|
|
|
|
/* return block to the heap memory pool */
|
|
|
|
k_mem_pool_free(ptr);
|
|
|
|
}
|
|
|
|
}
|
2017-04-18 16:42:09 -04:00
|
|
|
#endif
|
|
|
|
|