0
mirror of https://github.com/Indemsys/Frequency_Inverter.git synced 2026-06-17 03:37:42 +00:00
Files
2022-01-04 12:22:53 +02:00

1608 lines
52 KiB
C

/*HEADER*********************************************************************
*
* Copyright (c) 2008 Freescale Semiconductor;
* All Rights Reserved
*
* Copyright (c) 2004-2008 Embedded Access Inc.;
* All Rights Reserved
*
* Copyright (c) 1989-2008 ARC International;
* All Rights Reserved
*
***************************************************************************
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: partition.c$
* $Version : 3.8.2.0$
* $Date : Jun-25-2012$
*
* Comments:
*
* This file contains functions of the Partititon component.
*
*END************************************************************************/
#include "mqx_inc.h"
#if MQX_USE_PARTITIONS
#include "partition.h"
#include "partition_prv.h"
/*!
* \brief Allocates a private partition block from the partition.
*
* The functions allocate a fixed-size memory block, which the task owns.
*
* \param[in] partition Partition from which to allocate the partition block.
*
* \return Pointer to the partition block (success).
* \return NULL (failure)
*
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li PARTITION_INVALID (Partition does not represent a valid partition.)
* \li PARTITION_OUT_OF_BLOCKS (All the partition blocks in the partition are
* allocated (for static partitions only).)
* \li PARTITION_BLOCK_INVALID_CHECKSUM (MQX found an incorrect checksum in the
* partition block header.)
* \li Task error code set by _mem_alloc_system() MQX cannot allocate memory for
* the partition block (for dynamic partitions only).
*
* \see _partition_alloc_zero
* \see _partition_alloc_system
* \see _partition_alloc_system_zero
* \see _partition_create
* \see _task_set_error
* \see _mem_alloc_system
*/
pointer _partition_alloc
(
_partition_id partition
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
pointer result;
_GET_KERNEL_DATA(kernel_data);
_KLOGE2(KLOG_partition_alloc, partition);
result = _partition_alloc_internal((PARTPOOL_STRUCT_PTR) partition, kernel_data->ACTIVE_PTR);
_KLOGX2(KLOG_partition_alloc, result);
return (result);
} /* Endbody */
/*!
* \private
*
* \brief Allocates a private partition block from the partition.
*
* \param[in] partpool_ptr The partition to obtain the memory block from.
* \param[in] td_ptr The task to own the partition block.
*
* \return Pointer to the partition block (success).
* \return NULL (failure)
*
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li PARTITION_INVALID (Partition does not represent a valid partition.)
* \li PARTITION_OUT_OF_BLOCKS (All the partition blocks in the partition are
* allocated (for static partitions only).)
* \li PARTITION_BLOCK_INVALID_CHECKSUM (MQX found an incorrect checksum in the
* partition block header.)
* \li Task error code set by _mem_alloc_system() MQX cannot allocate memory for
* the partition block (for dynamic partitions only).
*/
pointer _partition_alloc_internal
(
PARTPOOL_STRUCT_PTR partpool_ptr,
TD_STRUCT_PTR td_ptr
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
INTERNAL_PARTITION_BLOCK_STRUCT_PTR block_ptr;
PARTPOOL_BLOCK_STRUCT_PTR partpool_block_ptr;
_mqx_uint number_of_blocks;
#if MQX_CHECK_ERRORS
if (partpool_ptr == NULL)
{
_task_set_error(PARTITION_INVALID);
return NULL;
} /* Endif */
#endif /* MQX_CHECK_ERRORS */
#if MQX_CHECK_VALIDITY
if (partpool_ptr->POOL.VALID != PARTITION_VALID)
{
_task_set_error(PARTITION_INVALID);
return NULL;
} /* Endif */
#endif /* MQX_CHECK_VALIDITY */
_GET_KERNEL_DATA(kernel_data);
_INT_DISABLE();
if (partpool_ptr->AVAILABLE == 0)
{
if ((partpool_ptr->PARTITION_TYPE == PARTITION_DYNAMIC) && partpool_ptr->GROW_BLOCKS
&& ((partpool_ptr->MAXIMUM_BLOCKS == 0) || (partpool_ptr->TOTAL_BLOCKS
< partpool_ptr->MAXIMUM_BLOCKS)))
{
/* We can attempt to grow the partition */
number_of_blocks = partpool_ptr->GROW_BLOCKS;
if ((partpool_ptr->MAXIMUM_BLOCKS != 0) && (number_of_blocks > (partpool_ptr->MAXIMUM_BLOCKS
- partpool_ptr->TOTAL_BLOCKS)))
{
number_of_blocks = partpool_ptr->MAXIMUM_BLOCKS - partpool_ptr->TOTAL_BLOCKS;
} /* Endif */
/*
* Temporarily boost up TOTAL BLOCKS to allow us to
* enable interrupts during memory allocation
*/
partpool_ptr->TOTAL_BLOCKS += number_of_blocks;
_int_enable();
#if PSP_MEMORY_ALIGNMENT
partpool_block_ptr = (PARTPOOL_BLOCK_STRUCT_PTR) _mem_alloc_system(
(_mem_size) (sizeof(PARTPOOL_BLOCK_STRUCT) + PSP_MEMORY_ALIGNMENT
+ (partpool_ptr->BLOCK_SIZE * number_of_blocks)));
#else
partpool_block_ptr = _mem_alloc_system((_mem_size)
(sizeof(PARTPOOL_BLOCK_STRUCT) +
(partpool_ptr->BLOCK_SIZE * number_of_blocks)));
#endif /* PSP_MEMORY_ALIGNMENT */
if (partpool_block_ptr != NULL)
{
_mem_set_type(partpool_block_ptr, MEM_TYPE_PARTITION_BLOCKS);
_partition_extend_internal(partpool_ptr, partpool_block_ptr, number_of_blocks);
}
else
{
partpool_ptr->TOTAL_BLOCKS -= number_of_blocks;
} /* Endif */
_int_disable();
} /* Endif */
if (((volatile PARTPOOL_STRUCT _PTR_) partpool_ptr)->AVAILABLE == 0)
{
_int_enable();
_task_set_error(PARTITION_OUT_OF_BLOCKS);
return NULL;
} /* Endif */
} /* Endif */
block_ptr = partpool_ptr->FREE_LIST_PTR;
#if MQX_CHECK_VALIDITY
if (!VALID_PARTITION_CHECKSUM(block_ptr))
{
_int_enable();
_task_set_error(PARTITION_BLOCK_INVALID_CHECKSUM);
return NULL;
} /* Endif */
#endif /* MQX_CHECK_VALIDITY */
partpool_ptr->FREE_LIST_PTR = block_ptr->LINK.NEXT_BLOCK_PTR;
--partpool_ptr->AVAILABLE;
if ((partpool_ptr->TOTAL_BLOCKS - partpool_ptr->AVAILABLE) > partpool_ptr->MAX_BLOCKS_USED)
{
partpool_ptr->MAX_BLOCKS_USED = partpool_ptr->TOTAL_BLOCKS - partpool_ptr->AVAILABLE;
}/* Endif */
block_ptr->TASK_ID = td_ptr->TASK_ID;
block_ptr->LINK.PARTITION_PTR = partpool_ptr;
CALC_PARTITION_CHECKSUM(block_ptr);
/* Reset partition test walker */
partpool_ptr->TEST_FREE_PTR = partpool_ptr->FREE_LIST_PTR;
_INT_ENABLE();
return (pointer) ((uchar_ptr) block_ptr + sizeof(INTERNAL_PARTITION_BLOCK_STRUCT));
} /* Endbody */
/*!
* \brief Gets the number of free partition blocks in the partition.
*
* \param[in] partition Partition about which to get info.
*
* \return Number of free partition blocks (success).
* \return MAX_MQX_UINT (failure)
*
* \warning On failure, calls _task_set_error() to set the following task error
* code:
* \li PARTITION_INVALID (Partition does not represent a valid partition.)
*
* \see _partition_get_block_size
* \see _partition_get_max_used_blocks
* \see _partition_get_total_blocks
* \see _partition_get_total_size
* \see _task_set_error
*/
_mqx_uint _partition_get_free_blocks
(
_partition_id partition
)
{ /* Body */
PARTPOOL_STRUCT_PTR partpool_ptr = (PARTPOOL_STRUCT_PTR) partition;
#if MQX_CHECK_VALIDITY
if (partpool_ptr->POOL.VALID != PARTITION_VALID)
{
_task_set_error(PARTITION_INVALID);
return (MAX_MQX_UINT);
} /* Endif */
#endif /* MQX_CHECK_VALIDITY */
return (partpool_ptr->AVAILABLE);
} /* Endbody */
/*!
* \brief Creates the partition kernel component.
*
* \return MQX_OK
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return MQX_OUT_OF_MEMORY (MQX is out of memory.)
*
* \warning Cannot be called from an ISR.
* \warning Might block the calling task.
*
* \see _partition_create
* \see _partition_destroy
*/
_mqx_uint _partition_create_component(void)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
PARTITION_COMPONENT_STRUCT_PTR part_component_ptr;
_GET_KERNEL_DATA(kernel_data);
_KLOGE1(KLOG_partition_create_component);
#if MQX_CHECK_ERRORS
if (kernel_data->IN_ISR)
{
_KLOGX2(KLOG_partition_create_component, MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
return (MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
} /* Endif */
#endif /* MQX_CHECK_ERRORS */
_lwsem_wait((LWSEM_STRUCT_PTR) &kernel_data->COMPONENT_CREATE_LWSEM);
#if MQX_CHECK_ERRORS
if (kernel_data->KERNEL_COMPONENTS[KERNEL_PARTITIONS] != NULL)
{
_lwsem_post((LWSEM_STRUCT_PTR) &kernel_data->COMPONENT_CREATE_LWSEM);
_KLOGX2(KLOG_partition_create_component, MQX_OK);
return (MQX_OK);
} /* Endif */
#endif /* MQX_CHECK_ERRORS */
part_component_ptr = _mem_alloc_system_zero((_mem_size) sizeof(PARTITION_COMPONENT_STRUCT));
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (part_component_ptr == NULL)
{
_lwsem_post((LWSEM_STRUCT_PTR) &kernel_data->COMPONENT_CREATE_LWSEM);
_KLOGX2(KLOG_partition_create_component, MQX_OUT_OF_MEMORY);
return (MQX_OUT_OF_MEMORY);
} /* Endif */
#endif /* MQX_CHECK_MEMORY_ALLOCATION_ERRORS */
_mem_set_type(part_component_ptr, MEM_TYPE_PARTITION_COMPONENT);
kernel_data->KERNEL_COMPONENTS[KERNEL_PARTITIONS] = part_component_ptr;
part_component_ptr->VALID = PARTITION_VALID;
_QUEUE_INIT(&part_component_ptr->PARTITIONS, 0);
#if MQX_COMPONENT_DESTRUCTION
kernel_data->COMPONENT_CLEANUP[KERNEL_PARTITIONS] = _partition_cleanup;
#endif /* MQX_COMPONENT_DESTRUCTION */
_lwsem_post((LWSEM_STRUCT_PTR) &kernel_data->COMPONENT_CREATE_LWSEM);
_KLOGX2(KLOG_partition_create_component, MQX_OK);
return (MQX_OK);
} /* Endbody */
/*!
* \brief Creates the partition at the specific location outside the default
* memory pool (a static partition).
*
* \param[in] partition_location Pointer to the start of the partition.
* \param[in] partition_size The size of the partition.
* \param[in] block_size Number of single-addressable units in each
* partition block in the partition.
*
* \return Partition ID (success).
* \return PARTITION_NULL_ID (failure)
*
* \warning Creates the partition component if it were not previously created.
* \warning On failure, calls _task_set_error() to set the following task error
* code:
* \li MAX_INVALID_PARAMETER (One of the following: block_size is 0 or
* partition_size is too small.)
*
* \see _partition_alloc
* \see _partition_alloc_zero
* \see _partition_alloc_system
* \see _partition_alloc_system_zero
* \see _partition_calculate_size
* \see _partition_create
* \see _partition_extend
* \see _task_set_error
*/
_partition_id _partition_create_at
(
pointer partition_location,
_mem_size partition_size,
_mem_size block_size
)
{ /* Body */
_KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;)
PARTPOOL_STRUCT_PTR partpool_ptr;
uchar_ptr firstblock_ptr;
_mqx_uint number_of_blocks;
_mqx_uint result;
_KLOGM(_GET_KERNEL_DATA(kernel_data);)
_KLOGE4(KLOG_partition_create_at, partition_location, partition_size, block_size);
#if MQX_CHECK_ERRORS
if (block_size == 0)
{
_task_set_error(MQX_INVALID_PARAMETER);
_KLOGX2(KLOG_partition_create_at, PARTITION_NULL_ID);
return (PARTITION_NULL_ID);
} /* Endif */
if (partition_size < sizeof(PARTPOOL_STRUCT))
{
_task_set_error(MQX_INVALID_PARAMETER);
_KLOGX2(KLOG_partition_create_at, PARTITION_NULL_ID);
return (PARTITION_NULL_ID);
} /* Endif */
#endif /* MQX_CHECK_ERRORS */
block_size += (_mem_size) sizeof(INTERNAL_PARTITION_BLOCK_STRUCT);
_MEMORY_ALIGN_VAL_LARGER(block_size);
partpool_ptr = (PARTPOOL_STRUCT_PTR)
_ALIGN_ADDR_TO_HIGHER_MEM(partition_location);
firstblock_ptr = (uchar_ptr) partpool_ptr + sizeof(PARTPOOL_STRUCT);
firstblock_ptr = (uchar_ptr) _ALIGN_ADDR_TO_HIGHER_MEM(firstblock_ptr);
partition_size -= (_mem_size) firstblock_ptr - (_mem_size) partition_location;
number_of_blocks = (_mqx_uint) (partition_size / block_size);
#if MQX_CHECK_ERRORS
if (!number_of_blocks)
{
_KLOGX2(KLOG_partition_create_at, PARTITION_NULL_ID);
return (PARTITION_NULL_ID);
} /* Endif */
#endif /* MQX_CHECK_ERRORS */
result = _partition_create_internal(partpool_ptr, block_size, number_of_blocks);
#if MQX_CHECK_ERRORS
if (result != MQX_OK)
{
_KLOGX2(KLOG_partition_create_at, result);
return (PARTITION_NULL_ID);
} /* Endif */
#endif /* MQX_CHECK_ERRORS */
partpool_ptr->PARTITION_TYPE = PARTITION_STATIC;
_KLOGX5(KLOG_partition_create_at, partpool_ptr, partition_size, block_size, MQX_OK);
return ((_partition_id) partpool_ptr);
} /* Endbody */
/*!
* \private
*
* \brief Create a partition at a location with a specified number of blocks.
*
* \param[in] partpool_ptr The start of the partition.
* \param[in] actual_size The total size of each block with overheads.
* \param[in] initial_blocks The initial number of blocks in the partition.
*
* \return MQX_OK
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return MQX_OUT_OF_MEMORY (MQX is out of memory.)
*/
_mqx_uint _partition_create_internal
(
PARTPOOL_STRUCT_PTR partpool_ptr,
_mem_size actual_size,
_mqx_uint initial_blocks
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
INTERNAL_PARTITION_BLOCK_STRUCT_PTR block_ptr;
PARTITION_COMPONENT_STRUCT_PTR part_component_ptr;
_mqx_uint result;
_GET_KERNEL_DATA(kernel_data);
part_component_ptr = (PARTITION_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_PARTITIONS];
if (part_component_ptr == NULL)
{
result = _partition_create_component();
part_component_ptr = (PARTITION_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_PARTITIONS];
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (part_component_ptr == NULL)
{
return (result);
} /* Endif */
#endif /* MQX_CHECK_MEMORY_ALLOCATION_ERRORS */
} /* Endif */
_mem_zero(partpool_ptr, (_mem_size) sizeof(PARTPOOL_STRUCT));
partpool_ptr->BLOCK_SIZE = actual_size;
partpool_ptr->POOL.VALID = PARTITION_VALID;
partpool_ptr->POOL.NUMBER_OF_BLOCKS = initial_blocks;
partpool_ptr->AVAILABLE = initial_blocks;
partpool_ptr->TOTAL_BLOCKS = initial_blocks;
block_ptr = (INTERNAL_PARTITION_BLOCK_STRUCT_PTR)((uchar_ptr) partpool_ptr + sizeof(PARTPOOL_STRUCT));
block_ptr = (INTERNAL_PARTITION_BLOCK_STRUCT_PTR)
_ALIGN_ADDR_TO_HIGHER_MEM(block_ptr);
partpool_ptr->POOL.FIRST_IBLOCK_PTR = block_ptr;
while (initial_blocks--)
{
block_ptr->LINK.NEXT_BLOCK_PTR = partpool_ptr->FREE_LIST_PTR;
CALC_PARTITION_CHECKSUM(block_ptr);
partpool_ptr->FREE_LIST_PTR = block_ptr;
block_ptr = (INTERNAL_PARTITION_BLOCK_STRUCT_PTR)((uchar_ptr) block_ptr + actual_size);
} /* Endwhile */
_int_disable();
_QUEUE_ENQUEUE(&part_component_ptr->PARTITIONS, partpool_ptr);
_int_enable();
return (MQX_OK);
} /* Endbody */
/*!
* \brief Creates the partition in the default memory pool (a dynamic partition).
*
* The function creates a partition of fixed-size partition blocks in the default
* memory pool.
*
* \param[in] block_size Number of single-addressable units in each partition
* block.
* \param[in] initial_blocks The initial number of blocks in the partition.
* \param[in] grow_blocks Number of blocks by which to grow the partition if
* all the partition blocks are allocated.
* \param[in] maximum_blocks If grow_blocks is not 0, one of:
* \li Maximum number of blocks in the partition.
* \li 0 (Unlimited growth.)
*
* \return Partition ID (success).
* \return PARTITION_NULL_ID (failure)
*
* \warning Creates the partition component if it were not previously created.
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li MQX_INVALID_PARAMETER (Block_size is 0.)
* \li Task error codes returned by _mem_alloc_system()
*
* \see _partition_alloc
* \see _partition_alloc_zero
* \see _partition_alloc_system
* \see _partition_alloc_system_zero
* \see _partition_calculate_size
* \see _partition_create_at
* \see _partition_destroy
* \see _task_set_error
* \see _mem_alloc_system
*/
_partition_id _partition_create
(
_mem_size block_size,
_mqx_uint initial_blocks,
_mqx_uint grow_blocks,
_mqx_uint maximum_blocks
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
PARTPOOL_STRUCT_PTR partpool_ptr;
_mem_size actual_size;
_mqx_uint result;
_GET_KERNEL_DATA(kernel_data);
_KLOGE5(KLOG_partition_create, block_size, initial_blocks, grow_blocks,
maximum_blocks);
#if MQX_CHECK_ERRORS
if (kernel_data->IN_ISR)
{
_task_set_error(MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
_KLOGX2(KLOG_partition_create, PARTITION_NULL_ID);
return (PARTITION_NULL_ID);
} /* Endif */
if (block_size == 0)
{
_task_set_error(MQX_INVALID_PARAMETER);
_KLOGX2(KLOG_partition_create, PARTITION_NULL_ID);
return (PARTITION_NULL_ID);
} /* Endif */
#endif /* MQX_CHECK_ERRORS */
actual_size = (_mem_size) sizeof(INTERNAL_PARTITION_BLOCK_STRUCT) + block_size;
_MEMORY_ALIGN_VAL_LARGER(actual_size);
#if PSP_MEMORY_ALIGNMENT
partpool_ptr = (PARTPOOL_STRUCT_PTR) _mem_alloc_system((_mem_size) (sizeof(PARTPOOL_STRUCT) + PSP_MEMORY_ALIGNMENT
+ (actual_size * initial_blocks)));
#else
partpool_ptr = ((PARTPOOL_STRUCT_PTR))_mem_alloc_system(
(_mem_size)(sizeof(PARTPOOL_STRUCT) + (actual_size * initial_blocks)));
#endif /* PSP_MEMORY_ALIGNMENT */
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (partpool_ptr == NULL)
{
_KLOGX2(KLOG_partition_create, PARTITION_NULL_ID);
return (PARTITION_NULL_ID);
}/* Endif */
#endif /* MQX_CHECK_MEMORY_ALLOCATION_ERRORS */
_mem_set_type(partpool_ptr, MEM_TYPE_PARTITION);
result = _partition_create_internal(partpool_ptr, actual_size, initial_blocks);
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (result != MQX_OK)
{
_KLOGX2(KLOG_partition_create, PARTITION_NULL_ID);
_mem_free(partpool_ptr);
return (PARTITION_NULL_ID);
} /* Endif */
#endif /* MQX_CHECK_MEMORY_ALLOCATION_ERRORS */
partpool_ptr->PARTITION_TYPE = PARTITION_DYNAMIC;
partpool_ptr->GROW_BLOCKS = grow_blocks;
partpool_ptr->MAXIMUM_BLOCKS = maximum_blocks;
_KLOGX3(KLOG_partition_create, partpool_ptr, MQX_OK);
return ((_partition_id) partpool_ptr);
} /* Endbody */
/*!
* \brief Destroys a partition that is in the default memory pool (a dynamic
* partition).
*
* If all the partition blocks in a dynamic partition are first freed, any task
* can destroy the partition.
*
* \param[in] partition Partition ID of the partition to destroy.
*
* \return MQX_OK
* \return MQX_COMPONENT_DOES_NOT_EXIST (Partition component is not created.)
* \return MQX_INVALID_PARAMETER (Partition_id is invalid.)
* \return PARTITION_INVALID_TYPE (Partition is not a dynamic partition.)
* \return PARTITION_ALL_BLOCKS_NOT_FREE (There are allocated partition blocks in
* the partition.)
* \return Errors from _mem_free()
*
* \see _mem_free
* \see _partition_create
* \see _partition_free
*/
_mqx_uint _partition_destroy
(
_partition_id partition
)
{ /* Body */
/* _KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;) */
KERNEL_DATA_STRUCT_PTR kernel_data;
PARTPOOL_STRUCT_PTR partpool_ptr;
PARTPOOL_BLOCK_STRUCT_PTR current_ptr;
PARTPOOL_BLOCK_STRUCT_PTR next_ptr;
_mqx_uint result;
PARTITION_COMPONENT_STRUCT_PTR part_component_ptr;
/* _KLOGM(_GET_KERNEL_DATA(kernel_data);) */
_GET_KERNEL_DATA(kernel_data);
_KLOGE2(KLOG_partition_destroy, partition);
part_component_ptr = (PARTITION_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_PARTITIONS];
partpool_ptr = (PARTPOOL_STRUCT_PTR) partition;
#if MQX_CHECK_ERRORS
if (part_component_ptr == NULL)
{
_KLOGX2(KLOG_partition_destroy, MQX_COMPONENT_DOES_NOT_EXIST);
return MQX_COMPONENT_DOES_NOT_EXIST;
} /* Endif */
if (partpool_ptr->POOL.VALID != PARTITION_VALID)
{
_KLOGX2(KLOG_partition_destroy, MQX_INVALID_PARAMETER);
return MQX_INVALID_PARAMETER;
} /* Endif */
if (partpool_ptr->PARTITION_TYPE != PARTITION_DYNAMIC)
{
_KLOGX2(KLOG_partition_destroy, PARTITION_INVALID_TYPE);
return PARTITION_INVALID_TYPE;
} /* Endif */
#endif /* MQX_CHECK_ERRORS */
if (partpool_ptr->TOTAL_BLOCKS != partpool_ptr->AVAILABLE)
{
_KLOGX2(KLOG_partition_destroy, PARTITION_ALL_BLOCKS_NOT_FREE);
return PARTITION_ALL_BLOCKS_NOT_FREE;
} /* Endif */
/* Remove the partition from the list of partitions maintained by MQX */
_int_disable();
_QUEUE_REMOVE(&part_component_ptr->PARTITIONS, partpool_ptr);
_int_enable();
partpool_ptr->POOL.VALID = 0;
/* Free any extensions */
current_ptr = partpool_ptr->POOL.NEXT_POOL_PTR;
while (current_ptr)
{
next_ptr = current_ptr->NEXT_POOL_PTR;
_mem_free(current_ptr);
current_ptr = next_ptr;
} /* Endwhile */
result = _mem_free(partpool_ptr);
_KLOGX2(KLOG_partition_destroy, result);
return result;
} /* Endbody */
/*!
* \brief Adds more blocks of memory to the static partition.
*
* The function extends a partition that was created with _partition_create_at().
* Based on the size of the partition's partition blocks, the function divides
* the additional memory into partition blocks and adds them to the partition.
*
* \param[in] partition Static partition to extend.
* \param[in] partition_location Where the additional blocks are to start from.
* \param[in] partition_size Number of single-addressable units to add.
*
* \return MQX_OK
* \return PARTITION_INVALID (Partition does not represent a valid partition.)
* \return MQX_INVALID_PARAMETER (One of the following:
* \li Partition_size is 0.
* \li Partition_id does not represent a static partition.)
*
* \see _partition_create_at
* \see _partition_alloc
* \see _partition_alloc_zero
*/
_mqx_uint _partition_extend
(
_partition_id partition,
pointer partition_location,
_mem_size partition_size
)
{ /* Body */
_KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;)
PARTPOOL_STRUCT_PTR partpool_ptr = (PARTPOOL_STRUCT_PTR) partition;
PARTPOOL_BLOCK_STRUCT_PTR partpool_block_ptr;
INTERNAL_PARTITION_BLOCK_STRUCT_PTR block_ptr;
_mqx_uint number_of_blocks;
_KLOGM(_GET_KERNEL_DATA(kernel_data);)
_KLOGE4(KLOG_partition_extend, partition, partition_location, partition_size);
#if MQX_CHECK_VALIDITY
if (partpool_ptr->POOL.VALID != PARTITION_VALID)
{
_KLOGX2(KLOG_partition_extend, PARTITION_INVALID);
return (PARTITION_INVALID);
} /* Endif */
#endif /* MQX_CHECK_VALIDITY */
#if MQX_CHECK_ERRORS
if (partpool_ptr->PARTITION_TYPE == PARTITION_DYNAMIC)
{
_KLOGX2(KLOG_partition_extend, MQX_INVALID_PARAMETER);
return (MQX_INVALID_PARAMETER);
} /* Endif */
#endif /* MQX_CHECK_ERRORS */
partpool_block_ptr = (PARTPOOL_BLOCK_STRUCT_PTR)
_ALIGN_ADDR_TO_HIGHER_MEM(partition_location);
partition_size = partition_size - (_mem_size) partpool_block_ptr + (_mem_size) partition_location;
_MEMORY_ALIGN_VAL_SMALLER(partition_size);
#if MQX_CHECK_ERRORS
if (partition_size < (_mem_size) sizeof(PARTPOOL_STRUCT))
{
_KLOGX2(KLOG_partition_extend, MQX_INVALID_PARAMETER);
return (MQX_INVALID_PARAMETER);
} /* Endif */
#endif /* MQX_CHECK_ERRORS */
block_ptr = (INTERNAL_PARTITION_BLOCK_STRUCT_PTR)((uchar_ptr) partpool_block_ptr + sizeof(PARTPOOL_BLOCK_STRUCT));
block_ptr = (INTERNAL_PARTITION_BLOCK_STRUCT_PTR)
_ALIGN_ADDR_TO_HIGHER_MEM(block_ptr);
number_of_blocks = (partition_size - ((uchar_ptr) block_ptr - (uchar_ptr) partpool_block_ptr))
/ partpool_ptr->BLOCK_SIZE;
partpool_ptr->TOTAL_BLOCKS += number_of_blocks;
_partition_extend_internal(partpool_ptr, partpool_block_ptr, number_of_blocks);
_KLOGX5(KLOG_partition_extend, partition, partpool_ptr, partition_size, MQX_OK);
return MQX_OK;
} /* Endbody */
/*!
* \private
*
* \brief Adds more blocks of memory into the partition.
*
* \param[in] partpool_ptr The partition to add to.
* \param[in] partpool_block_ptr The new block to add.
* \param[in] number_of_blocks The number of blocks to add.
*/
void _partition_extend_internal
(
PARTPOOL_STRUCT_PTR partpool_ptr,
PARTPOOL_BLOCK_STRUCT_PTR partpool_block_ptr,
_mqx_uint number_of_blocks
)
{ /* Body */
INTERNAL_PARTITION_BLOCK_STRUCT_PTR block_ptr;
partpool_block_ptr->VALID = PARTITION_VALID;
partpool_block_ptr->NUMBER_OF_BLOCKS = number_of_blocks;
block_ptr = (INTERNAL_PARTITION_BLOCK_STRUCT_PTR)((uchar_ptr) partpool_block_ptr + sizeof(PARTPOOL_BLOCK_STRUCT));
block_ptr = (INTERNAL_PARTITION_BLOCK_STRUCT_PTR)
_ALIGN_ADDR_TO_HIGHER_MEM(block_ptr);
partpool_block_ptr->FIRST_IBLOCK_PTR = block_ptr;
while (number_of_blocks--)
{
_int_disable();
block_ptr->LINK.NEXT_BLOCK_PTR = partpool_ptr->FREE_LIST_PTR;
CALC_PARTITION_CHECKSUM(block_ptr);
partpool_ptr->FREE_LIST_PTR = block_ptr;
partpool_ptr->AVAILABLE++;
_int_enable();
block_ptr = (INTERNAL_PARTITION_BLOCK_STRUCT_PTR)((uchar_ptr) block_ptr + partpool_ptr->BLOCK_SIZE);
} /* Endwhile */
_int_disable();
partpool_block_ptr->NEXT_POOL_PTR = partpool_ptr->POOL.NEXT_POOL_PTR;
partpool_ptr->POOL.NEXT_POOL_PTR = partpool_block_ptr;
_int_enable();
} /* Endbody */
/*!
* \brief Frees the selected partition block and returns it to the partition.
*
* Partition blocks created by _partition_alloc() or _partition_alloc_zero() can
* be freed only by task, that allocated them. However when partition block was
* created by _partition_alloc_system() or _partition_alloc_system_zero(), then
* it can be freed by any task.
*
* \param[in] mem_ptr Pointer to the partition block to free.
*
* \return MQX_OK
* \return PARTITION_BLOCK_INVALID_CHECKSUM (Checksum in the partition block
* header is not correct; the integrity of the partition is in question.)
* \return MQX_NOT_RESOURCE_OWNER (Task is not the one that owns the partition block.)
* \return PARTITION_INVALID (Mem_ptr is part of a partition that is not valid.)
*
* \see _partition_alloc
* \see _partition_alloc_zero
* \see _partition_alloc_system
* \see _partition_alloc_system_zero
* \see _partition_create
*/
_mqx_uint _partition_free
(
pointer mem_ptr
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
PARTPOOL_STRUCT_PTR partpool_ptr;
INTERNAL_PARTITION_BLOCK_STRUCT_PTR block_ptr;
_GET_KERNEL_DATA(kernel_data);
_KLOGE2(KLOG_partition_free, mem_ptr);
block_ptr = (INTERNAL_PARTITION_BLOCK_STRUCT_PTR)((uchar_ptr) mem_ptr - sizeof(INTERNAL_PARTITION_BLOCK_STRUCT));
#if MQX_CHECK_VALIDITY
if (!VALID_PARTITION_CHECKSUM(block_ptr))
{
_KLOGX2(KLOG_partition_free, PARTITION_BLOCK_INVALID_CHECKSUM);
return (PARTITION_BLOCK_INVALID_CHECKSUM);
} /* Endif */
#endif /* MQX_CHECK_VALIDITY */
#if MQX_CHECK_ERRORS
if (block_ptr->TASK_ID != SYSTEM_TD_PTR(kernel_data)->TASK_ID)
{
/* Let system blocks be freed by anyone */
if (block_ptr->TASK_ID != kernel_data->ACTIVE_PTR->TASK_ID)
{
_KLOGX2(KLOG_partition_free, MQX_NOT_RESOURCE_OWNER);
return (MQX_NOT_RESOURCE_OWNER);
} /* Endif */
} /* Endif */
#endif /* MQX_CHECK_ERRORS */
partpool_ptr = block_ptr->LINK.PARTITION_PTR;
_INT_DISABLE();
#if MQX_CHECK_VALIDITY
if (partpool_ptr->POOL.VALID != PARTITION_VALID)
{
_int_enable();
_KLOGX2(KLOG_partition_free, PARTITION_INVALID);
return (PARTITION_INVALID);
} /* Endif */
#endif /* MQX_CHECK_VALIDITY */
block_ptr->TASK_ID = 0;
block_ptr->LINK.NEXT_BLOCK_PTR = partpool_ptr->FREE_LIST_PTR;
partpool_ptr->FREE_LIST_PTR = block_ptr;
++partpool_ptr->AVAILABLE;
CALC_PARTITION_CHECKSUM(block_ptr);
_INT_ENABLE();
_KLOGX2(KLOG_partition_free, MQX_OK);
return (MQX_OK);
} /* Endbody */
/*!
* \brief Allocates a system partition block from the partition.
*
* The functions allocate a fixed-size block of memory that is not owned by any
* task.
*
* \param[in] partition Partition from which to allocate the partition block.
*
* \return Pointer to the partition block (success).
* \return NULL (failure)
*
* \warning On failure, calls _task_set_error() to set one of the task error codes
* described for _partition_alloc().
*
* \see _partition_alloc_system_zero
* \see _partition_alloc
* \see _partition_alloc_zero
* \see _partition_create
* \see _task_set_error
*/
pointer _partition_alloc_system
(
_partition_id partition
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
pointer result;
_GET_KERNEL_DATA(kernel_data);
_KLOGE2(KLOG_partition_alloc_system, partition);
result = _partition_alloc_internal((PARTPOOL_STRUCT_PTR) partition, SYSTEM_TD_PTR(kernel_data));
_KLOGX2(KLOG_partition_alloc_system, result);
return (result);
} /* Endbody */
/*!
* \brief Allocates a zero-filled system partition block from the partition.
*
* The functions allocate a fixed-size block of memory that is not owned by any
* task.
*
* \param[in] partition Partition from which to allocate the partition block.
*
* \return Pointer to the partition block (success).
* \return NULL (failure)
*
* \warning On failure, calls _task_set_error() to set one of the task error codes
* described for _partition_alloc().
*
* \see _partition_alloc_system
* \see _partition_alloc
* \see _partition_alloc_zero
* \see _partition_create
* \see _task_set_error
*/
pointer _partition_alloc_system_zero
(
_partition_id partition
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
PARTPOOL_STRUCT_PTR partpool_ptr = (PARTPOOL_STRUCT_PTR) partition;
pointer result;
_GET_KERNEL_DATA(kernel_data);
_KLOGE2(KLOG_partition_alloc_system_zero, partition);
result = _partition_alloc_internal(partpool_ptr, SYSTEM_TD_PTR(kernel_data));
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (result == NULL)
{
_KLOGX2(KLOG_partition_alloc_system_zero, result);
return (result);
} /* Endif */
#endif /* MQX_CHECK_MEMORY_ALLOCATION_ERRORS */
_mem_zero(result, (_mem_size) (partpool_ptr->BLOCK_SIZE - sizeof(INTERNAL_PARTITION_BLOCK_STRUCT)));
_KLOGX2(KLOG_partition_alloc_system_zero, result);
return (result);
} /* Endbody */
/*!
* \brief Returns all partition blocks owned by the task to the pool.
*
* \param[in] td_ptr The task being destroyed.
*/
void _partition_cleanup
(
TD_STRUCT_PTR td_ptr
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
PARTPOOL_STRUCT_PTR partpool_ptr;
PARTPOOL_BLOCK_STRUCT_PTR partpool_block_ptr;
PARTITION_COMPONENT_STRUCT_PTR part_component_ptr;
INTERNAL_PARTITION_BLOCK_STRUCT_PTR block_ptr;
_mqx_uint i;
_GET_KERNEL_DATA(kernel_data);
part_component_ptr = (PARTITION_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_PARTITIONS];
if (part_component_ptr == NULL)
{
return; /* No work to do! */
} /* Endif */
#if MQX_CHECK_VALIDITY
if (part_component_ptr->VALID != PARTITION_VALID)
{
return;
} /* Endif */
#endif /* MQX_CHECK_VALIDITY */
partpool_ptr = (PARTPOOL_STRUCT_PTR)((pointer) part_component_ptr->PARTITIONS.NEXT);
while (partpool_ptr != (PARTPOOL_STRUCT_PTR)((pointer) &part_component_ptr->PARTITIONS))
{
/* Check each partition */
partpool_block_ptr = &partpool_ptr->POOL;
while (partpool_block_ptr != NULL)
{
/* Check each poolblock in the partition */
#if MQX_CHECK_VALIDITY
if (partpool_block_ptr->VALID != PARTITION_VALID)
{
break;
}/* Endif */
#endif /* MQX_CHECK_VALIDITY */
block_ptr = partpool_block_ptr->FIRST_IBLOCK_PTR;
i = partpool_block_ptr->NUMBER_OF_BLOCKS + 1;
while (--i)
{
if ((block_ptr->TASK_ID == td_ptr->TASK_ID) && (block_ptr->LINK.PARTITION_PTR == partpool_ptr))
{ /* An allocated Block */
_int_disable();
block_ptr->LINK.NEXT_BLOCK_PTR = partpool_ptr->FREE_LIST_PTR;
partpool_ptr->FREE_LIST_PTR = block_ptr;
++partpool_ptr->AVAILABLE;
CALC_PARTITION_CHECKSUM(block_ptr);
_int_enable();
} /* Endif */
block_ptr = (INTERNAL_PARTITION_BLOCK_STRUCT_PTR)((uchar_ptr) block_ptr + partpool_ptr->BLOCK_SIZE);
} /* Endwhile */
partpool_block_ptr = partpool_block_ptr->NEXT_POOL_PTR;
} /* Endwhile */
partpool_ptr = (PARTPOOL_STRUCT_PTR) partpool_ptr->NEXT;
} /* Endwhile */
} /* Endbody */
/*!
* \brief Tests all partition block checksums for validity.
*
* \param[out] partpool_in_error Pointer to the partition pool in error
* (initialized only if an error is found).
* \param[out] partpool_block_in_error Pointer to the partition pool block in
* error (internal to MQX).
* \param[out] block_in_error Pointer to the partition block in error
* (initialized only if an error is found).
*
* \return MQX_OK (No partitions have errors.)
* \return MQX_INVALID_COMPONENT_BASE (Partition component data are not valid.)
* \return PARTITION_INVALID (MQX found an invalid partition.)
* \return PARTITION_BLOCK_INVALID_CHECKSUM (MQX found a partition block with an
* incorrect checksum.)
* \return MQX_CORRUPT_QUEUE (An error is found.)
*
* \warning Disables and enables interrupts.
*
* \see _partition_alloc
* \see _partition_alloc_zero
* \see _partition_alloc_system
* \see _partition_alloc_system_zero
* \see _partition_create
* \see _partition_free
*/
_mqx_uint _partition_test
(
_partition_id _PTR_ partpool_in_error,
pointer _PTR_ partpool_block_in_error,
pointer _PTR_ block_in_error
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
PARTPOOL_STRUCT_PTR partpool_ptr;
PARTPOOL_BLOCK_STRUCT_PTR partpool_block_ptr;
INTERNAL_PARTITION_BLOCK_STRUCT_PTR block_ptr;
PARTITION_COMPONENT_STRUCT_PTR part_component_ptr;
_mqx_uint i;
_mqx_uint result;
_GET_KERNEL_DATA(kernel_data);
_KLOGE1(KLOG_partition_test);
part_component_ptr = (PARTITION_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_PARTITIONS];
if (part_component_ptr == NULL)
{
_KLOGX2(KLOG_partition_test, MQX_OK);
return (MQX_OK);
} /* Endif */
#if MQX_CHECK_VALIDITY
if (part_component_ptr->VALID != PARTITION_VALID)
{
_KLOGX2(KLOG_partition_test, MQX_INVALID_COMPONENT_BASE);
return (MQX_INVALID_COMPONENT_BASE);
} /* Endif */
#endif /* MQX_CHECK_VALIDITY */
_int_disable();
/* Make sure that the queue of partitions is ok */
result = _queue_test(&part_component_ptr->PARTITIONS, partpool_in_error);
_int_enable();
if (result != MQX_OK)
{
_KLOGX3(KLOG_partition_test, result, *partpool_in_error);
return (result);
} /* Endif */
partpool_ptr = (PARTPOOL_STRUCT_PTR)((pointer) part_component_ptr->PARTITIONS.NEXT);
while (partpool_ptr != (PARTPOOL_STRUCT_PTR)((pointer) &part_component_ptr->PARTITIONS))
{
/* Check all partitions */
*partpool_in_error = partpool_ptr;
partpool_block_ptr = &partpool_ptr->POOL;
while (partpool_block_ptr != NULL)
{
/* Check all partition pool blocks contiguously */
*partpool_block_in_error = partpool_block_ptr;
block_ptr = partpool_block_ptr->FIRST_IBLOCK_PTR;
i = partpool_block_ptr->NUMBER_OF_BLOCKS + 1;
while (--i)
{
#if MQX_CHECK_VALIDITY
if (partpool_ptr->POOL.VALID != PARTITION_VALID)
{
*block_in_error = NULL;
_KLOGX2(KLOG_partition_test, PARTITION_INVALID);
return (PARTITION_INVALID);
} /* Endif */
#endif /* MQX_CHECK_VALIDITY */
_int_disable();
if (!VALID_PARTITION_CHECKSUM(block_ptr))
{
_int_enable();
*block_in_error = (pointer) ((uchar_ptr) block_ptr + sizeof(INTERNAL_PARTITION_BLOCK_STRUCT));
_KLOGX2(KLOG_partition_test, PARTITION_BLOCK_INVALID_CHECKSUM);
return (PARTITION_BLOCK_INVALID_CHECKSUM);
} /* Endif */
_int_enable();
block_ptr = (INTERNAL_PARTITION_BLOCK_STRUCT_PTR)((uchar_ptr) block_ptr + partpool_ptr->BLOCK_SIZE);
} /* Endwhile */
partpool_block_ptr = partpool_block_ptr->NEXT_POOL_PTR;
} /* Endwhile */
/* Check partition free list */
_int_disable();
block_ptr = partpool_ptr->FREE_LIST_PTR;
while (block_ptr != NULL)
{
partpool_ptr->TEST_FREE_PTR = block_ptr;
_int_enable();
_int_disable();
block_ptr = (INTERNAL_PARTITION_BLOCK_STRUCT_PTR) partpool_ptr->TEST_FREE_PTR;
if (!VALID_PARTITION_CHECKSUM(block_ptr))
{
_int_enable();
*block_in_error = (pointer) ((uchar_ptr) block_ptr + sizeof(INTERNAL_PARTITION_BLOCK_STRUCT));
_KLOGX2(KLOG_partition_test, PARTITION_BLOCK_INVALID_CHECKSUM);
return (PARTITION_BLOCK_INVALID_CHECKSUM);
} /* Endif */
block_ptr = block_ptr->LINK.NEXT_BLOCK_PTR;
} /* Endwhile */
partpool_ptr = (PARTPOOL_STRUCT_PTR) partpool_ptr->NEXT;
_int_enable();
} /* Endwhile */
_KLOGX2(KLOG_partition_test, MQX_OK);
return MQX_OK;
} /* Endbody */
/*!
* \brief Transfers the ownership of the partition block.
*
* Any task can transfer the ownership of a private partition block or a system
* partition block.
* \n If new_owner_id is the System Task ID, the partition block becomes a system
* partition block.
* \n If the ownership of a system partition block is transferred to a task, the
* partition block becomes a resource of the task.
*
* \param[in] mem_ptr Pointer to the partition block to transfer.
* \param[in] new_owner_id Task ID of the new owner.
*
* \return MQX_OK
* \return PARTITION_BLOCK_INVALID_CHECKSUM (Checksum of the partition block
* header is not correct, which indicates that mem_ptr might not point to a valid
* partition block.)
* \return PARTITION_INVALID_TASK_ID (Task_id is not valid.)
*
* \see _partition_alloc
* \see _partition_alloc_zero
* \see _partition_alloc_system
* \see _partition_alloc_system_zero
*/
_mqx_uint _partition_transfer
(
pointer mem_ptr,
_task_id new_owner_id
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
TD_STRUCT_PTR new_td_ptr;
INTERNAL_PARTITION_BLOCK_STRUCT_PTR block_ptr;
_GET_KERNEL_DATA(kernel_data);
_KLOGE3(KLOG_partition_transfer, mem_ptr, new_owner_id);
block_ptr = (INTERNAL_PARTITION_BLOCK_STRUCT_PTR)((uchar_ptr) mem_ptr - sizeof(INTERNAL_PARTITION_BLOCK_STRUCT));
#if MQX_CHECK_VALIDITY
if (!VALID_PARTITION_CHECKSUM(block_ptr))
{
_KLOGX2(KLOG_partition_transfer, PARTITION_BLOCK_INVALID_CHECKSUM);
return (PARTITION_BLOCK_INVALID_CHECKSUM);
} /* Endif */
#endif /* MQX_CHECK_VALIDITY */
new_td_ptr = (TD_STRUCT_PTR) _task_get_td(new_owner_id);
#if MQX_CHECK_ERRORS
if (new_td_ptr == NULL)
{
_KLOGX2(KLOG_partition_transfer, PARTITION_INVALID_TASK_ID);
return (PARTITION_INVALID_TASK_ID);
} /* Endif */
#endif /* MQX_CHECK_ERRORS */
_INT_DISABLE();
block_ptr->TASK_ID = new_owner_id;
CALC_PARTITION_CHECKSUM(block_ptr);
_INT_ENABLE();
_KLOGX2(KLOG_partition_transfer, MQX_OK);
return (MQX_OK);
} /* Endbody */
/*!
* \brief Gets the number of allocated partition blocks in the partition.
*
* \param[in] partition The partition to obtain information about.
*
* \return Number of allocated partition blocks (success).
* \return 0 (failure)
*
* \warning On failure, calls _task_set_error() to set the following task error
* code:
* \li PARTITION_INVALID (Partition does not represent a valid partition.)
*
* \see _partition_get_block_size
* \see _partition_get_free_blocks
* \see _partition_get_total_blocks
* \see _partition_get_total_size
* \see _task_set_error
*/
_mqx_uint _partition_get_max_used_blocks
(
_partition_id partition
)
{ /* Body */
PARTPOOL_STRUCT_PTR partpool_ptr = (PARTPOOL_STRUCT_PTR) partition;
#if MQX_CHECK_VALIDITY
if (partpool_ptr->POOL.VALID != PARTITION_VALID)
{
_task_set_error(PARTITION_INVALID);
return 0;
} /* Endif */
#endif /* MQX_CHECK_VALIDITY */
return (partpool_ptr->MAX_BLOCKS_USED);
} /* Endbody */
/*!
* \brief Gets the total number of partition blocks in the partition.
*
* The function returns the sum of the number of free partition blocks and the
* number of allocated partition blocks in the partition.
*
* \param[in] partition The partition to obtain information about.
*
* \return Total number of partition blocks in the partition (success).
* \return 0 (failure)
*
* \warning On failure, calls _task_set_error() to set the following task error
* code:
* \li PARTITION_INVALID (Partition does not represent a valid partition.)
*
* \see _partition_get_block_size
* \see _partition_get_free_blocks
* \see _partition_get_max_used_blocks
* \see _partition_get_total_size
* \see _task_set_error
*/
_mqx_uint _partition_get_total_blocks
(
_partition_id partition
)
{ /* Body */
PARTPOOL_STRUCT_PTR partpool_ptr = (PARTPOOL_STRUCT_PTR) partition;
#if MQX_CHECK_VALIDITY
if (partpool_ptr->POOL.VALID != PARTITION_VALID)
{
_task_set_error(PARTITION_INVALID);
return 0;
} /* Endif */
#endif /* MQX_CHECK_VALIDITY */
return (partpool_ptr->TOTAL_BLOCKS);
} /* Endbody */
/*!
* \brief Gets the size of the partition blocks in the partition.
*
* If the processor supports memory alignment, the function might return a value
* that is larger that what was specified when the partition was created.
*
* \param[in] partition The partition to obtain information about.
*
* \return Number of single-addressable units in a partition block (success).
* \return 0 (failure)
*
* \warning On failure, calls _task_set_error() to set the following task error
* code:
* \li PARTITION_INVALID (Partition does not represent a valid partition.)
*
* \see _partition_get_free_blocks
* \see _partition_get_max_used_blocks
* \see _partition_get_total_blocks
* \see _partition_get_total_size
* \see _partition_create_at
* \see _task_set_error
*/
_mem_size _partition_get_block_size
(
_partition_id partition
)
{ /* Body */
PARTPOOL_STRUCT_PTR partpool_ptr = (PARTPOOL_STRUCT_PTR) partition;
#if MQX_CHECK_VALIDITY
if (partpool_ptr->POOL.VALID != PARTITION_VALID)
{
_task_set_error(PARTITION_INVALID);
return 0;
} /* Endif */
#endif /* MQX_CHECK_VALIDITY */
return (partpool_ptr->BLOCK_SIZE - (_mem_size) sizeof(INTERNAL_PARTITION_BLOCK_STRUCT));
} /* Endbody */
/*!
* \brief Gets the size of the partition.
*
* The size of the partition includes extensions and internal overhead.
*
* \param[in] partition The partition to obtain information about.
*
* \return Number of single-addressable units in the partition (success).
* \return 0 (failure)
*
* \warning On failure, calls _task_set_error() to set the following task error
* code:
* \li PARTITION_INVALID (Partition does not represent a valid partition.)
*
* \see _partition_get_block_size
* \see _partition_get_free_blocks
* \see _partition_get_max_used_blocks
* \see _partition_get_total_blocks
* \see _partition_extend
* \see _task_set_error
*/
_mem_size _partition_get_total_size
(
_partition_id partition
)
{ /* Body */
PARTPOOL_STRUCT_PTR partpool_ptr = (PARTPOOL_STRUCT_PTR) partition;
PARTPOOL_BLOCK_STRUCT_PTR partpool_block_ptr;
register _mem_size size;
uchar_ptr tmp_ptr;
#if MQX_CHECK_VALIDITY
if (partpool_ptr->POOL.VALID != PARTITION_VALID)
{
_task_set_error(PARTITION_INVALID);
return 0;
} /* Endif */
#endif /* MQX_CHECK_VALIDITY */
size = 0;
partpool_block_ptr = partpool_ptr->POOL.NEXT_POOL_PTR;
while (partpool_block_ptr != NULL)
{
tmp_ptr = (uchar_ptr) partpool_block_ptr + sizeof(PARTPOOL_BLOCK_STRUCT);
tmp_ptr = (uchar_ptr) _ALIGN_ADDR_TO_HIGHER_MEM(tmp_ptr);
size += (_mem_size) (tmp_ptr - (uchar_ptr) partpool_block_ptr);
partpool_block_ptr = partpool_block_ptr->NEXT_POOL_PTR;
} /* Endif */
tmp_ptr = (uchar_ptr) partition + sizeof(PARTPOOL_STRUCT);
tmp_ptr = (uchar_ptr) _ALIGN_ADDR_TO_HIGHER_MEM(tmp_ptr);
size += (_mem_size) (tmp_ptr - (uchar_ptr) partition);
return (size + partpool_ptr->BLOCK_SIZE * partpool_ptr->TOTAL_BLOCKS);
} /* Endbody */
/*!
* \brief Calculates the number of single-addressable units in a partition.
*
* If an application wants to use as much as possible of some memory that is
* outside the default memory pool, it can use the function to determine the
* maximum number of blocks that can be created.
* \n For a dynamic partition, the application might want to limit (based on the
* results of the function) the amount of memory in the default memory pool that
* it uses to create the partition.
*
* \param[in] number_of_blocks Number of partition blocks in the partition.
* \param[in] block_size Number of single-addressable units in one partition
* block in the partition.
*
* \return Number of single-addressable units in the partition.
*
* \see _partition_calculate_blocks
* \see _partition_create
* \see _partition_create_at
*/
_mem_size _partition_calculate_size
(
_mqx_uint number_of_blocks,
_mem_size block_size
)
{ /* Body */
_mem_size actual_block_size;
_mem_size size;
actual_block_size = sizeof(INTERNAL_PARTITION_BLOCK_STRUCT) + block_size;
_MEMORY_ALIGN_VAL_LARGER(actual_block_size);
#if PSP_MEMORY_ALIGNMENT
size = sizeof(PARTPOOL_STRUCT) + PSP_MEMORY_ALIGNMENT + actual_block_size * number_of_blocks;
#else
size = sizeof(PARTPOOL_STRUCT) + actual_block_size * number_of_blocks;
#endif /* PSP_MEMORY_ALIGNMENT */
return (size);
} /* Endbody */
/*!
* /brief Calculates the number of partition blocks in a static partition.
*
* When a task creates a static partition (_partition_create_at()), it specifies
* the size of the partition and the size of partition blocks. The function
* _partition_calculate_blocks() calculates how many blocks MQX actually created,
* taking into account internal headers.
*
* \param[in] partition_size Number of single-addressable units that the partition
* can occupy.
* \param[in] block_size Number of single-addressable units in one partition
* block of the partition.
*
* \return Number of partition blocks in the partition.
*
* \see _partition_calculate_size
* \see _partition_create_at
*/
_mqx_uint _partition_calculate_blocks
(
_mem_size partition_size,
_mem_size block_size
)
{ /* Body */
_mem_size actual_size;
_mem_size size;
actual_size = sizeof(INTERNAL_PARTITION_BLOCK_STRUCT) + block_size;
_MEMORY_ALIGN_VAL_LARGER(actual_size);
size = (_mem_size) sizeof(PARTPOOL_STRUCT);
_MEMORY_ALIGN_VAL_LARGER(size);
return ((_mqx_uint) ((partition_size - size) / actual_size));
} /* Endbody */
/*!
* \brief Gets size of partition.
*
* \return Size of partition (Success).
* \return 0 (Failure)
*/
_mqx_uint _partition_get_number_of(void)
{
uint_32 count = 0;
KERNEL_DATA_STRUCT_PTR kernel_data;
PARTITION_COMPONENT_STRUCT_PTR part_component_ptr;
_GET_KERNEL_DATA(kernel_data);
part_component_ptr = (PARTITION_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_PARTITIONS];
if (part_component_ptr)
{
count = part_component_ptr->PARTITIONS.SIZE;
}
else
{
count = 0;
} /* Endif */
return count;
}
/*!
* \brief Allocates a zero-filled private partition block from the partition.
*
* The functions allocate a fixed-size memory block, which the task owns.
*
* \param[in] partition Partition from which to allocate the partition block.
*
* \return Pointer to the partition block (success).
* \return NULL (failure)
*
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li PARTITION_INVALID (Partition does not represent a valid partition.)
* \li PARTITION_OUT_OF_BLOCKS (All the partition blocks in the partition are
* allocated (for static partitions only).)
* \li PARTITION_BLOCK_INVALID_CHECKSUM (MQX found an incorrect checksum in the
* partition block header.)
* \li Task error code set by _mem_alloc_system() MQX cannot allocate memory for
* the partition block (for dynamic partitions only).
*
* \see _partition_alloc
* \see _partition_alloc_system
* \see _partition_alloc_system_zero
* \see _partition_create
* \see _task_set_error
* \see _mem_alloc_system
*/
pointer _partition_alloc_zero
(
_partition_id partition
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
PARTPOOL_STRUCT_PTR partpool_ptr = (PARTPOOL_STRUCT_PTR) partition;
pointer result;
_GET_KERNEL_DATA(kernel_data);
_KLOGE2(KLOG_partition_alloc_zero, partition);
result = _partition_alloc_internal(partpool_ptr, kernel_data->ACTIVE_PTR);
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (result == NULL)
{
_KLOGX2(KLOG_partition_alloc_zero, result);
return (result);
} /* Endif */
#endif /* MQX_CHECK_MEMORY_ALLOCATION_ERRORS */
_mem_zero(result, (_mem_size) (partpool_ptr->BLOCK_SIZE - sizeof(INTERNAL_PARTITION_BLOCK_STRUCT)));
_KLOGX2(KLOG_partition_alloc_zero, result);
return (result);
} /* Endbody */
#endif /* MQX_USE_PARTITIONS */
/* EOF */