mirror of
https://github.com/eclipse-threadx/threadx.git
synced 2025-11-16 04:24:48 +00:00
update to v6.1.3
This commit is contained in:
@@ -10,37 +10,40 @@
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Module Interface (API) */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Module Interface (API) */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* APPLICATION INTERFACE DEFINITION RELEASE */
|
||||
/* */
|
||||
/* txm_module.h PORTABLE C */
|
||||
/* 6.1 */
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* APPLICATION INTERFACE DEFINITION RELEASE */
|
||||
/* */
|
||||
/* txm_module.h PORTABLE C */
|
||||
/* 6.1.3 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the basic module constants, interface structures, */
|
||||
/* and function prototypes. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the basic module constants, interface structures, */
|
||||
/* and function prototypes. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* 12-31-2020 Scott Larson Modified comment(s), added */
|
||||
/* port-specific extension, */
|
||||
/* resulting in version 6.1.3 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -329,6 +332,8 @@ extern "C" {
|
||||
#define TXM_MODULE_OBJECT_ALLOCATE_CALL 95
|
||||
#define TXM_MODULE_OBJECT_DEALLOCATE_CALL 96
|
||||
|
||||
#define TXM_MODULE_PORT_EXTENSION_API_ID_START 500
|
||||
#define TXM_MODULE_PORT_EXTENSION_API_ID_END 999
|
||||
|
||||
/* Determine the API call IDs for other components. */
|
||||
|
||||
@@ -508,7 +513,7 @@ typedef struct TXM_MODULE_ALLOCATED_OBJECT_STRUCT
|
||||
*txm_module_allocated_object_next,
|
||||
*txm_module_allocated_object_previous;
|
||||
ULONG txm_module_object_size;
|
||||
} TXM_MODULE_ALLOCATED_OBJECT;
|
||||
} TXM_MODULE_ALLOCATED_OBJECT;
|
||||
|
||||
|
||||
/* Determine if module code is being compiled. If so, remap the ThreadX API to
|
||||
@@ -571,6 +576,7 @@ VOID _txm_module_usbx_duo_callback_request(TXM_MODULE_CALLBACK_MESSAGE *callbac
|
||||
resident portion of the application. */
|
||||
|
||||
#define txm_module_manager_initialize _txm_module_manager_initialize
|
||||
#define txm_module_manager_absolute_load _txm_module_manager_absolute_load
|
||||
#define txm_module_manager_in_place_load _txm_module_manager_in_place_load
|
||||
#define txm_module_manager_file_load _txm_module_manager_file_load
|
||||
#define txm_module_manager_memory_load _txm_module_manager_memory_load
|
||||
@@ -607,6 +613,7 @@ UINT _txm_module_manager_application_request(ULONG request, ALIGN_TYPE param_1,
|
||||
UINT _txm_module_manager_file_load(TXM_MODULE_INSTANCE *module_instance, CHAR *module_name, FX_MEDIA *media_ptr, CHAR *file_name);
|
||||
#endif
|
||||
UINT _txm_module_manager_initialize(VOID *module_memory_start, ULONG module_memory_size);
|
||||
UINT _txm_module_manager_absolute_load(TXM_MODULE_INSTANCE *module_instance, CHAR *name, VOID *module_location);
|
||||
UINT _txm_module_manager_in_place_load(TXM_MODULE_INSTANCE *module_instance, CHAR *name, VOID *module_location);
|
||||
UINT _txm_module_manager_internal_load(TXM_MODULE_INSTANCE *module_instance, CHAR *name, VOID *module_location,
|
||||
ULONG code_size, VOID *code_allocation_ptr, ULONG code_allocation_size);
|
||||
|
||||
@@ -0,0 +1,439 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_initialize.h"
|
||||
#include "tx_mutex.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_byte_pool.h"
|
||||
#include "txm_module.h"
|
||||
#include "txm_module_manager_util.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_absolute_load PORTABLE C */
|
||||
/* 6.1.3 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Andres Mlinar, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function ensures the code-related and data-related parts of */
|
||||
/* the module preamble are valid and prepares the module for */
|
||||
/* execution. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* module_instance Module instance pointer */
|
||||
/* module_name Module name pointer */
|
||||
/* module_location Module code location */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_byte_allocate Allocate data area */
|
||||
/* _tx_mutex_get Get protection mutex */
|
||||
/* _tx_mutex_put Release protection mutex */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 12-31-2020 Andres Mlinar Initial Version 6.1.3 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _txm_module_manager_absolute_load(TXM_MODULE_INSTANCE *module_instance, CHAR *module_name, VOID *module_location)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TXM_MODULE_PREAMBLE *module_preamble;
|
||||
ULONG code_size;
|
||||
ULONG code_alignment;
|
||||
ULONG code_allocation_size_ignored;
|
||||
UINT status;
|
||||
|
||||
TXM_MODULE_INSTANCE *next_module, *previous_module;
|
||||
ULONG start_stop_stack_size;
|
||||
ULONG callback_stack_size;
|
||||
ULONG code_size_ignored;
|
||||
ULONG code_alignment_ignored;
|
||||
ALIGN_TYPE data_start;
|
||||
ULONG data_size;
|
||||
ULONG data_alignment;
|
||||
ULONG data_allocation_size;
|
||||
ULONG module_properties;
|
||||
CHAR *memory_ptr;
|
||||
|
||||
|
||||
/* Check for interrupt call. */
|
||||
if (TX_THREAD_GET_SYSTEM_STATE() != 0)
|
||||
{
|
||||
|
||||
/* Now, make sure the call is from an interrupt and not initialization. */
|
||||
if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
|
||||
{
|
||||
|
||||
/* Invalid caller of this function, return appropriate error code. */
|
||||
return(TX_CALLER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the module manager has not been initialized yet. */
|
||||
if (_txm_module_manager_ready != TX_TRUE)
|
||||
{
|
||||
|
||||
/* Module manager has not been initialized. */
|
||||
return(TX_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
/* Determine if the module is valid. */
|
||||
if (module_instance == TX_NULL)
|
||||
{
|
||||
|
||||
/* Invalid module pointer. */
|
||||
return(TX_PTR_ERROR);
|
||||
}
|
||||
|
||||
/* Get module manager protection mutex. */
|
||||
_tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
|
||||
|
||||
/* Determine if the module is already valid. */
|
||||
if (module_instance -> txm_module_instance_id == TXM_MODULE_ID)
|
||||
{
|
||||
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* Module already loaded. */
|
||||
return(TXM_MODULE_ALREADY_LOADED);
|
||||
}
|
||||
|
||||
/* Pickup the module's information. */
|
||||
module_preamble = (TXM_MODULE_PREAMBLE *) module_location;
|
||||
|
||||
/* Check to make sure there is a valid module to load. */
|
||||
if (module_preamble -> txm_module_preamble_id != TXM_MODULE_ID)
|
||||
{
|
||||
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* Invalid module preamble. */
|
||||
return(TXM_MODULE_INVALID);
|
||||
}
|
||||
|
||||
/* Check the properties of this module. */
|
||||
module_properties = module_preamble -> txm_module_preamble_property_flags & TXM_MODULE_OPTIONS_MASK;
|
||||
if (/* Ensure the requested properties are supported. */
|
||||
((module_properties & _txm_module_manager_properties_supported) != module_properties) ||
|
||||
/* Ensure the required properties are there. */
|
||||
((_txm_module_manager_properties_required & module_properties) != _txm_module_manager_properties_required) ||
|
||||
/* If memory protection is enabled, then so must user mode. */
|
||||
((module_properties & TXM_MODULE_MEMORY_PROTECTION) && !(module_properties & TXM_MODULE_USER_MODE))
|
||||
)
|
||||
{
|
||||
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* Invalid properties. Return error. */
|
||||
return(TXM_MODULE_INVALID_PROPERTIES);
|
||||
}
|
||||
|
||||
/* Check for valid module entry offsets. */
|
||||
if ((module_preamble -> txm_module_preamble_shell_entry_function == 0) ||
|
||||
(module_preamble -> txm_module_preamble_start_function == 0))
|
||||
{
|
||||
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* Invalid module preamble. */
|
||||
return(TXM_MODULE_INVALID);
|
||||
}
|
||||
|
||||
/* Check for valid sizes. */
|
||||
if ((module_preamble -> txm_module_preamble_code_size == 0) ||
|
||||
/* (module_preamble -> txm_module_preamble_data_size == 0) || *** a zero data size is valid */
|
||||
(module_preamble -> txm_module_preamble_start_stop_stack_size == 0) ||
|
||||
(module_preamble -> txm_module_preamble_callback_stack_size == 0))
|
||||
{
|
||||
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* Invalid module preamble. */
|
||||
return(TXM_MODULE_INVALID);
|
||||
}
|
||||
|
||||
/* Get the amount of the bytes we need to allocate for the module's code
|
||||
as well as the required alignment. Note that because this is an absolute
|
||||
load, we only want the code alignment so we can check it. */
|
||||
status = _txm_module_manager_util_code_allocation_size_and_alignment_get(module_preamble, &code_alignment, &code_allocation_size_ignored);
|
||||
if (status != TX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Math overflow error occurred. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Since this is an absolute load, check the alignment of the module's instruction area (code). */
|
||||
TXM_MODULE_MANAGER_CHECK_CODE_ALIGNMENT(module_location, code_alignment)
|
||||
|
||||
/* Initialize module control block to all zeros. */
|
||||
TX_MEMSET(module_instance, 0, sizeof(TXM_MODULE_INSTANCE));
|
||||
|
||||
/* Pickup the basic module sizes. */
|
||||
code_size = module_preamble -> txm_module_preamble_code_size;
|
||||
data_size = module_preamble -> txm_module_preamble_data_size;
|
||||
start_stop_stack_size = module_preamble -> txm_module_preamble_start_stop_stack_size;
|
||||
callback_stack_size = module_preamble -> txm_module_preamble_callback_stack_size;
|
||||
|
||||
TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_size, TXM_MODULE_DATA_ALIGNMENT, data_size);
|
||||
data_size = ((data_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
|
||||
|
||||
/* Adjust the size of the module elements to be aligned to the default alignment. We do this
|
||||
so that when we partition the allocated memory, we can simply place these regions right beside
|
||||
each other without having to align their pointers. Note this only works when they all have
|
||||
the same alignment. */
|
||||
|
||||
TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(start_stop_stack_size, TXM_MODULE_DATA_ALIGNMENT, start_stop_stack_size);
|
||||
start_stop_stack_size = ((start_stop_stack_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
|
||||
|
||||
TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(callback_stack_size, TXM_MODULE_DATA_ALIGNMENT, callback_stack_size);
|
||||
callback_stack_size = ((callback_stack_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
|
||||
|
||||
/* Update the data size to account for the default thread stacks. */
|
||||
data_allocation_size = 0;
|
||||
TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, start_stop_stack_size, data_allocation_size);
|
||||
TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, callback_stack_size, data_allocation_size);
|
||||
|
||||
/* Setup the default code and data alignments. */
|
||||
data_alignment = (ULONG) TXM_MODULE_DATA_ALIGNMENT;
|
||||
|
||||
/* Get the port-specific alignment for the data size. Note we only want data
|
||||
so we pass values of 1 for code (to avoid any possible div by 0 errors). */
|
||||
code_size_ignored = 1;
|
||||
code_alignment_ignored = 1;
|
||||
TXM_MODULE_MANAGER_ALIGNMENT_ADJUST(module_preamble, code_size_ignored, code_alignment_ignored, data_allocation_size, data_alignment)
|
||||
|
||||
/* Calculate the module's total RAM memory requirement. This entire area is allocated from the module
|
||||
manager's byte pool. The general layout is defined as follows:
|
||||
|
||||
Lowest Address: Start of start/stop thread stack
|
||||
... [note: thread entry info is embedded near end of stack areas]
|
||||
End of start/stop thread stack
|
||||
|
||||
Start of callback thread stack
|
||||
... [note: thread entry info is embedded near end of stack areas]
|
||||
End of callback thread stack
|
||||
|
||||
Highest Address: */
|
||||
|
||||
/* Add an extra alignment increment so we can align the pointer after allocation. */
|
||||
TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, data_alignment, data_allocation_size);
|
||||
|
||||
/* Allocate memory for the module. */
|
||||
status = _tx_byte_allocate(&_txm_module_manager_byte_pool, (VOID **) &memory_ptr, data_allocation_size, TX_NO_WAIT);
|
||||
|
||||
/* Determine if the module memory allocation was successful. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* No memory, return an error. */
|
||||
return(TX_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Clear the allocated memory. */
|
||||
TX_MEMSET(memory_ptr, ((UCHAR) 0), data_allocation_size);
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Setup the module instance structure. */
|
||||
module_instance -> txm_module_instance_id = TXM_MODULE_ID;
|
||||
|
||||
/* Save the module name. */
|
||||
module_instance -> txm_module_instance_name = module_name;
|
||||
|
||||
/* Save the module properties. */
|
||||
module_instance -> txm_module_instance_property_flags = module_preamble -> txm_module_preamble_property_flags;
|
||||
|
||||
/* Set the module data memory allocation. This is the address released
|
||||
when the module is unloaded. */
|
||||
module_instance -> txm_module_instance_data_allocation_ptr = (VOID *) memory_ptr;
|
||||
|
||||
/* Save the data allocation size. */
|
||||
module_instance -> txm_module_instance_data_allocation_size = data_allocation_size;
|
||||
|
||||
/* Calculate the actual start of the data area. This needs to be adjusted based on the alignment. */
|
||||
data_start = (ALIGN_TYPE) memory_ptr;
|
||||
data_start = (data_start + (((ALIGN_TYPE)data_alignment) - 1)) & ~(((ALIGN_TYPE)data_alignment) - 1);
|
||||
memory_ptr = (CHAR *) data_start;
|
||||
|
||||
/* Compute the beginning and end of the data area. */
|
||||
#ifdef ALIGN_TYPE_DEFINED
|
||||
module_instance -> txm_module_instance_data_start = (VOID *) (((CHAR *) (ALIGN_TYPE) module_preamble->txm_module_preamble_code_size) + sizeof(TXM_MODULE_PREAMBLE));
|
||||
module_instance -> txm_module_instance_data_end = (VOID *) (((CHAR *) (ALIGN_TYPE) module_instance -> txm_module_instance_data_start) + module_preamble->txm_module_preamble_data_size);
|
||||
#else
|
||||
module_instance -> txm_module_instance_data_start = (VOID *) (((CHAR *) module_preamble->txm_module_preamble_code_size) + sizeof(TXM_MODULE_PREAMBLE));
|
||||
module_instance -> txm_module_instance_data_end = (VOID *) (((CHAR *) module_instance -> txm_module_instance_data_start) + module_preamble->txm_module_preamble_data_size);
|
||||
#endif
|
||||
|
||||
/* Save the size of the data area. */
|
||||
module_instance -> txm_module_instance_data_size = data_size;
|
||||
|
||||
/* Set the module code memory allocation. This is the address released
|
||||
when the module is unloaded. */
|
||||
module_instance -> txm_module_instance_code_allocation_ptr = (VOID *) NULL;
|
||||
|
||||
/* Save the code allocation size. */
|
||||
module_instance -> txm_module_instance_code_allocation_size = 0;
|
||||
|
||||
/* Setup the code pointers. Since the code was loaded in-place, this is effectively just the values supplied in the API call. */
|
||||
module_instance -> txm_module_instance_code_start = (VOID *) module_location;
|
||||
module_instance -> txm_module_instance_code_end = (VOID *) (((CHAR *) module_location) + (code_size - 1));
|
||||
|
||||
/* Setup the code size. */
|
||||
module_instance -> txm_module_instance_code_size = code_size;
|
||||
|
||||
/* Save the module's total memory usage. */
|
||||
module_instance -> txm_module_instance_total_ram_usage = 0 /* Code is executed in place */ + data_allocation_size /* just the size of stacks */;
|
||||
|
||||
/* Set the module state to started. */
|
||||
module_instance -> txm_module_instance_state = TXM_MODULE_LOADED;
|
||||
|
||||
/* Save the preamble pointer. */
|
||||
module_instance -> txm_module_instance_preamble_ptr = module_preamble;
|
||||
|
||||
/* Save the module application ID in the module instance. */
|
||||
module_instance -> txm_module_instance_application_module_id = module_preamble -> txm_module_preamble_application_module_id;
|
||||
|
||||
/* Setup the module's start/stop thread stack area. */
|
||||
module_instance -> txm_module_instance_start_stop_stack_start_address = (VOID *) (memory_ptr);
|
||||
module_instance -> txm_module_instance_start_stop_stack_size = start_stop_stack_size;
|
||||
module_instance -> txm_module_instance_start_stop_stack_end_address = (VOID *) (memory_ptr + (start_stop_stack_size - 1));
|
||||
|
||||
/* Move the memory pointer forward. */
|
||||
memory_ptr = memory_ptr + start_stop_stack_size;
|
||||
|
||||
/* Save the start/stop thread priority. */
|
||||
module_instance -> txm_module_instance_start_stop_priority = module_preamble -> txm_module_preamble_start_stop_priority;
|
||||
|
||||
/* Setup the module's callback thread stack area. */
|
||||
module_instance -> txm_module_instance_callback_stack_start_address = (VOID *) (memory_ptr);
|
||||
module_instance -> txm_module_instance_callback_stack_size = callback_stack_size;
|
||||
module_instance -> txm_module_instance_callback_stack_end_address = (VOID *) (memory_ptr + (callback_stack_size - 1));
|
||||
|
||||
/* Move the memory pointer forward. */
|
||||
memory_ptr = memory_ptr + callback_stack_size;
|
||||
|
||||
/* Save the callback thread priority. */
|
||||
module_instance -> txm_module_instance_callback_priority = module_preamble -> txm_module_preamble_callback_priority;
|
||||
|
||||
/* Setup the start of the module data section. */
|
||||
module_instance -> txm_module_instance_module_data_base_address = (VOID *) (memory_ptr);
|
||||
|
||||
/* Build actual addresses based on load... Setup all the function pointers. Any adjustments needed to shell entry, start function, and callback function are defined in the
|
||||
module preamble. */
|
||||
#ifdef ALIGN_TYPE_DEFINED
|
||||
module_instance -> txm_module_instance_shell_entry_function = (VOID (*)(TX_THREAD *, TXM_MODULE_INSTANCE *)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_shell_entry_function);
|
||||
module_instance -> txm_module_instance_start_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_start_function);
|
||||
module_instance -> txm_module_instance_callback_request_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_callback_function);
|
||||
#else
|
||||
module_instance -> txm_module_instance_shell_entry_function = (VOID (*)(TX_THREAD *, TXM_MODULE_INSTANCE *)) ((VOID *) module_preamble -> txm_module_preamble_shell_entry_function);
|
||||
module_instance -> txm_module_instance_start_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_start_function);
|
||||
module_instance -> txm_module_instance_callback_request_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_callback_function);
|
||||
#endif
|
||||
|
||||
/* Determine if there is a stop function for this module. */
|
||||
if (module_preamble -> txm_module_preamble_stop_function)
|
||||
{
|
||||
|
||||
/* Yes, there is a stop function, build the address. */
|
||||
#ifdef ALIGN_TYPE_DEFINED
|
||||
module_instance -> txm_module_instance_stop_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_stop_function);
|
||||
#else
|
||||
module_instance -> txm_module_instance_stop_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_stop_function);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No, there is no stop function. Just set the pointer to NULL. */
|
||||
module_instance -> txm_module_instance_stop_thread_entry = TX_NULL;
|
||||
}
|
||||
|
||||
/* Load the module control block with port-specific information. */
|
||||
TXM_MODULE_MANAGER_MODULE_SETUP(module_instance);
|
||||
|
||||
/* Now add the module to the linked list of created modules. */
|
||||
if (_txm_module_manger_loaded_count++ == 0)
|
||||
{
|
||||
|
||||
/* The loaded module list is empty. Add module to empty list. */
|
||||
_txm_module_manager_loaded_list_ptr = module_instance;
|
||||
module_instance -> txm_module_instance_loaded_next = module_instance;
|
||||
module_instance -> txm_module_instance_loaded_previous = module_instance;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add to the end of the list. */
|
||||
next_module = _txm_module_manager_loaded_list_ptr;
|
||||
previous_module = next_module -> txm_module_instance_loaded_previous;
|
||||
|
||||
/* Place the new module in the list. */
|
||||
next_module -> txm_module_instance_loaded_previous = module_instance;
|
||||
previous_module -> txm_module_instance_loaded_next = module_instance;
|
||||
|
||||
/* Setup this module's created links. */
|
||||
module_instance -> txm_module_instance_loaded_previous = previous_module;
|
||||
module_instance -> txm_module_instance_loaded_next = next_module;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* Return success. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
@@ -12,8 +12,8 @@
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
@@ -36,50 +36,53 @@
|
||||
#include "txm_module_manager_util.h"
|
||||
#include "txm_module_manager_dispatch.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_kernel_dispatch PORTABLE C */
|
||||
/* 6.1 */
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_kernel_dispatch PORTABLE C */
|
||||
/* 6.1.3 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function dispatches the module's kernel request based upon the */
|
||||
/* ID and parameters specified in the request. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* kernel_request Module's kernel request */
|
||||
/* param_1 First parameter */
|
||||
/* param_2 Second parameter */
|
||||
/* param_3 Third parameter */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _txm_module_manager_application_request Application-specific req */
|
||||
/* _txm_module_manager_object_pointer_get Find object pointer */
|
||||
/* _txm_module_manager_thread_create Module thread create */
|
||||
/* [_txm_module_manager_*_dispatch] Optional external */
|
||||
/* component dispatch */
|
||||
/* ThreadX API Calls */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function dispatches the module's kernel request based upon the */
|
||||
/* ID and parameters specified in the request. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* kernel_request Module's kernel request */
|
||||
/* param_1 First parameter */
|
||||
/* param_2 Second parameter */
|
||||
/* param_3 Third parameter */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _txm_module_manager_application_request Application-specific req */
|
||||
/* _txm_module_manager_object_pointer_get Find object pointer */
|
||||
/* _txm_module_manager_thread_create Module thread create */
|
||||
/* [_txm_module_manager_*_dispatch] Optional external */
|
||||
/* component dispatch */
|
||||
/* ThreadX API Calls */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* 12-31-2020 Scott Larson Modified comment(s), added */
|
||||
/* port-specific dispatch, */
|
||||
/* resulting in version 6.1.3 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
ALIGN_TYPE _txm_module_manager_kernel_dispatch(ULONG kernel_request, ALIGN_TYPE param_0, ALIGN_TYPE param_1, ALIGN_TYPE param_2)
|
||||
@@ -679,6 +682,15 @@ TXM_MODULE_INSTANCE *module_instance;
|
||||
|
||||
default:
|
||||
{
|
||||
#ifdef TXM_MODULE_PORT_DISPATCH
|
||||
/* Is this a port-specific request? */
|
||||
if ((kernel_request >= TXM_MODULE_PORT_EXTENSION_API_ID_START) && (kernel_request <= TXM_MODULE_PORT_EXTENSION_API_ID_END))
|
||||
{
|
||||
/* Yes, call the port-specific dispatcher. */
|
||||
return_value = (ALIGN_TYPE) _txm_module_manager_port_dispatch(module_instance, kernel_request, param_0, param_1, param_2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Determine if an application request is present. */
|
||||
if (kernel_request >= TXM_APPLICATION_REQUEST_ID_BASE)
|
||||
{
|
||||
|
||||
@@ -10,15 +10,15 @@
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
@@ -29,47 +29,48 @@
|
||||
#include "txm_module.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_start PORTABLE C */
|
||||
/* 6.1 */
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_start PORTABLE C */
|
||||
/* 6.1.3 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function starts execution of the specified module. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* module_instance Module instance pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _txm_module_manager_name_build Build module:thread name */
|
||||
/* _txm_module_manager_thread_create Module thread create */
|
||||
/* _tx_mutex_get Get protection mutex */
|
||||
/* _tx_mutex_put Release protection mutex */
|
||||
/* _tx_queue_create Create module callback queue */
|
||||
/* _tx_queue_delete Delete module callback queue */
|
||||
/* _tx_thread_resume Resume start thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function starts execution of the specified module. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* module_instance Module instance pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _txm_module_manager_thread_create Module thread create */
|
||||
/* _tx_mutex_get Get protection mutex */
|
||||
/* _tx_mutex_put Release protection mutex */
|
||||
/* _tx_queue_create Create module callback queue */
|
||||
/* _tx_queue_delete Delete module callback queue */
|
||||
/* _tx_thread_resume Resume start thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* 12-31-2020 Scott Larson Modified comment(s), */
|
||||
/* resulting in version 6.1.3 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _txm_module_manager_start(TXM_MODULE_INSTANCE *module_instance)
|
||||
|
||||
@@ -21,11 +21,15 @@
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
#define TX_THREAD_SMP_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_initialize.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_initialize.h"
|
||||
#include "tx_timer.h"
|
||||
#include "txm_module.h"
|
||||
|
||||
@@ -35,7 +39,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_thread_create PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* 6.1.3 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -47,22 +51,22 @@
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Thread control block pointer */
|
||||
/* name Pointer to thread name string */
|
||||
/* shell_function Shell function of the thread */
|
||||
/* entry_function Entry function of the thread */
|
||||
/* entry_input 32-bit input value to thread */
|
||||
/* stack_start Pointer to start of stack */
|
||||
/* stack_size Stack size in bytes */
|
||||
/* priority Priority of thread */
|
||||
/* (default 0-31) */
|
||||
/* preempt_threshold Preemption threshold */
|
||||
/* time_slice Thread time-slice value */
|
||||
/* auto_start Automatic start selection */
|
||||
/* thread_ptr Thread control block pointer */
|
||||
/* name Pointer to thread name string */
|
||||
/* shell_function Shell function of the thread */
|
||||
/* entry_function Entry function of the thread */
|
||||
/* entry_input 32-bit input value to thread */
|
||||
/* stack_start Pointer to start of stack */
|
||||
/* stack_size Stack size in bytes */
|
||||
/* priority Priority of thread */
|
||||
/* (default 0-31) */
|
||||
/* preempt_threshold Preemption threshold */
|
||||
/* time_slice Thread time-slice value */
|
||||
/* auto_start Automatic start selection */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* return status Thread create return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
@@ -81,35 +85,41 @@
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* 12-31-2020 Scott Larson Modified comment(s), */
|
||||
/* fix stack overlap checking, */
|
||||
/* added 64-bit support, */
|
||||
/* added SMP support, */
|
||||
/* resulting in version 6.1.3 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _txm_module_manager_thread_create(TX_THREAD *thread_ptr, CHAR *name, VOID (*shell_function)(TX_THREAD *, TXM_MODULE_INSTANCE *),
|
||||
VOID (*entry_function)(ULONG), ULONG entry_input,
|
||||
VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold,
|
||||
ULONG time_slice, UINT auto_start, UINT thread_control_block_size, TXM_MODULE_INSTANCE *module_instance)
|
||||
UINT _txm_module_manager_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr,
|
||||
VOID (*shell_function)(TX_THREAD *, TXM_MODULE_INSTANCE *),
|
||||
VOID (*entry_function)(ULONG id), ULONG entry_input,
|
||||
VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold,
|
||||
ULONG time_slice, UINT auto_start,
|
||||
UINT thread_control_block_size, TXM_MODULE_INSTANCE *module_instance)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
#ifdef TX_THREAD_SMP
|
||||
UINT core_index;
|
||||
#endif
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
TX_THREAD *saved_thread_ptr;
|
||||
UINT saved_threshold = 0;
|
||||
TX_THREAD *saved_thread_ptr;
|
||||
UINT saved_threshold = ((UINT) 0);
|
||||
#endif
|
||||
UCHAR *temp_ptr;
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
ULONG new_stack_start;
|
||||
#endif
|
||||
TXM_MODULE_THREAD_ENTRY_INFO *thread_entry_info;
|
||||
VOID *stack_end;
|
||||
ULONG i;
|
||||
#ifndef TX_TIMER_PROCESS_IN_ISR
|
||||
TX_THREAD *current_thread;
|
||||
#endif
|
||||
#if TXM_MODULE_MEMORY_PROTECTION
|
||||
ULONG status;
|
||||
ALIGN_TYPE new_stack_start;
|
||||
ALIGN_TYPE updated_stack_start;
|
||||
#endif
|
||||
TXM_MODULE_THREAD_ENTRY_INFO *thread_entry_info;
|
||||
VOID *stack_end;
|
||||
ULONG i;
|
||||
|
||||
/* First, check for an invalid thread pointer. */
|
||||
if (thread_ptr == TX_NULL)
|
||||
@@ -150,37 +160,12 @@ ULONG status;
|
||||
}
|
||||
|
||||
/* Check the stack pointer to see if it overlaps with this thread's stack. */
|
||||
|
||||
/*lint -e{946} suppress pointer comparison, since this is necessary. */
|
||||
if (((UCHAR *) ((VOID *) stack_start)) >= ((UCHAR *) ((VOID *) next_thread -> tx_thread_stack_start)))
|
||||
if ((((UCHAR *) ((VOID *) stack_start)) <= ((UCHAR *) ((VOID *) next_thread -> tx_thread_stack_end))) &&
|
||||
(((UCHAR *) ((VOID *) stack_end)) >= ((UCHAR *) ((VOID *) next_thread -> tx_thread_stack_start))))
|
||||
{
|
||||
|
||||
/*lint -e{946} suppress pointer comparison, since this is necessary. */
|
||||
if (((UCHAR *) ((VOID *) stack_start)) < ((UCHAR *) ((VOID *) next_thread -> tx_thread_stack_end)))
|
||||
{
|
||||
|
||||
/* This stack overlaps with an existing thread, clear the stack pointer to
|
||||
force a stack error below. */
|
||||
stack_start = TX_NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the end of the stack to see if it is inside this thread's stack area as well. */
|
||||
|
||||
/*lint -e{946} suppress pointer comparison, since this is necessary. */
|
||||
if (((UCHAR *) ((VOID *) stack_end)) >= ((UCHAR *) ((VOID *) next_thread -> tx_thread_stack_start)))
|
||||
{
|
||||
|
||||
/*lint -e{946} suppress pointer comparison, since this is necessary. */
|
||||
if (((UCHAR *) ((VOID *) stack_end)) < ((UCHAR *) ((VOID *) next_thread -> tx_thread_stack_end)))
|
||||
{
|
||||
|
||||
/* This stack overlaps with an existing thread, clear the stack pointer to
|
||||
force a stack error below. */
|
||||
stack_start = TX_NULL;
|
||||
break;
|
||||
}
|
||||
/* Stacks overlap, clear the stack pointer to force a stack error below. */
|
||||
stack_start = TX_NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move to the next thread. */
|
||||
@@ -256,16 +241,19 @@ ULONG status;
|
||||
}
|
||||
|
||||
#ifndef TX_TIMER_PROCESS_IN_ISR
|
||||
|
||||
/* Pickup thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(current_thread)
|
||||
|
||||
/* Check for invalid caller of this function. First check for a calling thread. */
|
||||
if (current_thread == &_tx_timer_thread)
|
||||
{
|
||||
TX_THREAD *current_thread;
|
||||
|
||||
/* Invalid caller of this function, return appropriate error code. */
|
||||
return(TX_CALLER_ERROR);
|
||||
/* Pickup thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(current_thread)
|
||||
|
||||
/* Check for invalid caller of this function. First check for a calling thread. */
|
||||
if (current_thread == &_tx_timer_thread)
|
||||
{
|
||||
|
||||
/* Invalid caller of this function, return appropriate error code. */
|
||||
return(TX_CALLER_ERROR);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -295,21 +283,22 @@ ULONG status;
|
||||
/* Ensure that there are two ULONG of 0xEF patterns at the top and
|
||||
bottom of the thread's stack. This will be used to check for stack
|
||||
overflow conditions during run-time. */
|
||||
stack_size = ((stack_size/sizeof(ULONG)) * sizeof(ULONG)) - sizeof(ULONG);
|
||||
stack_size = ((stack_size/(sizeof(ULONG))) * (sizeof(ULONG))) - (sizeof(ULONG));
|
||||
|
||||
/* Ensure the starting stack address is evenly aligned. */
|
||||
new_stack_start = ((((ULONG) stack_start) + (sizeof(ULONG) - 1) ) & (~(sizeof(ULONG) - 1)));
|
||||
new_stack_start = TX_POINTER_TO_ALIGN_TYPE_CONVERT(stack_start);
|
||||
updated_stack_start = ((((ULONG) new_stack_start) + ((sizeof(ULONG)) - ((ULONG) 1)) ) & (~((sizeof(ULONG)) - ((ULONG) 1))));
|
||||
|
||||
/* Determine if the starting stack address is different. */
|
||||
if (new_stack_start != ((ULONG) stack_start))
|
||||
if (new_stack_start != updated_stack_start)
|
||||
{
|
||||
|
||||
/* Yes, subtract another ULONG from the size to avoid going past the stack area. */
|
||||
stack_size = stack_size - sizeof(ULONG);
|
||||
stack_size = stack_size - (sizeof(ULONG));
|
||||
}
|
||||
|
||||
/* Update the starting stack pointer. */
|
||||
stack_start = (VOID *) new_stack_start;
|
||||
stack_start = TX_ALIGN_TYPE_TO_POINTER_CONVERT(updated_stack_start);
|
||||
#endif
|
||||
|
||||
/* Allocate the thread entry information at the top of thread's stack - Leaving one
|
||||
@@ -321,53 +310,81 @@ ULONG status;
|
||||
|
||||
/* Initialize thread control block to all zeros. */
|
||||
TX_MEMSET(thread_ptr, 0, sizeof(TX_THREAD));
|
||||
|
||||
|
||||
#if TXM_MODULE_MEMORY_PROTECTION
|
||||
/* If this is a memory protected module, allocate a kernel stack. */
|
||||
if((module_instance -> txm_module_instance_property_flags) & TXM_MODULE_MEMORY_PROTECTION)
|
||||
{
|
||||
ULONG status;
|
||||
|
||||
/* Allocate kernel stack space. */
|
||||
status = _txm_module_manager_object_allocate((VOID **) &(thread_ptr -> tx_thread_module_kernel_stack_start), TXM_MODULE_KERNEL_STACK_SIZE, module_instance);
|
||||
if(status)
|
||||
{
|
||||
return(status);
|
||||
}
|
||||
|
||||
|
||||
#ifndef TX_DISABLE_STACK_FILLING
|
||||
/* Set the thread stack to a pattern prior to creating the initial
|
||||
stack frame. This pattern is used by the stack checking routines
|
||||
to see how much has been used. */
|
||||
TX_MEMSET(thread_ptr -> tx_thread_module_kernel_stack_start, ((UCHAR) TX_STACK_FILL), TXM_MODULE_KERNEL_STACK_SIZE);
|
||||
#endif
|
||||
|
||||
|
||||
/* Align kernel stack pointer. */
|
||||
thread_ptr -> tx_thread_module_kernel_stack_end = (VOID *) (((ALIGN_TYPE)(thread_ptr -> tx_thread_module_kernel_stack_start) + TXM_MODULE_KERNEL_STACK_SIZE) & ~0x07);
|
||||
|
||||
/* Set kernel stack size. */
|
||||
thread_ptr -> tx_thread_module_kernel_stack_size = TXM_MODULE_KERNEL_STACK_SIZE;
|
||||
}
|
||||
|
||||
|
||||
/* Place the stack parameters into the thread's control block. */
|
||||
thread_ptr -> tx_thread_module_stack_start = stack_start;
|
||||
thread_ptr -> tx_thread_module_stack_size = stack_size;
|
||||
thread_ptr -> tx_thread_module_stack_start = stack_start;
|
||||
thread_ptr -> tx_thread_module_stack_size = stack_size;
|
||||
#endif
|
||||
|
||||
/* Place the supplied parameters into the thread's control block. */
|
||||
thread_ptr -> tx_thread_name = name;
|
||||
thread_ptr -> tx_thread_entry = entry_function;
|
||||
thread_ptr -> tx_thread_entry_parameter = entry_input;
|
||||
thread_ptr -> tx_thread_stack_start = stack_start;
|
||||
thread_ptr -> tx_thread_stack_size = stack_size;
|
||||
thread_ptr -> tx_thread_stack_end = (VOID *) (((UCHAR *) stack_start) + (stack_size-1));
|
||||
thread_ptr -> tx_thread_name = name_ptr;
|
||||
thread_ptr -> tx_thread_entry = entry_function;
|
||||
thread_ptr -> tx_thread_entry_parameter = entry_input;
|
||||
thread_ptr -> tx_thread_stack_start = stack_start;
|
||||
thread_ptr -> tx_thread_stack_size = stack_size;
|
||||
thread_ptr -> tx_thread_priority = priority;
|
||||
thread_ptr -> tx_thread_user_priority = priority;
|
||||
thread_ptr -> tx_thread_time_slice = time_slice;
|
||||
thread_ptr -> tx_thread_new_time_slice = time_slice;
|
||||
thread_ptr -> tx_thread_inherit_priority = ((UINT) TX_MAX_PRIORITIES);
|
||||
#ifdef TX_THREAD_SMP
|
||||
thread_ptr -> tx_thread_smp_core_executing = ((UINT) TX_THREAD_SMP_MAX_CORES);
|
||||
thread_ptr -> tx_thread_smp_cores_excluded = ((ULONG) 0);
|
||||
#ifndef TX_THREAD_SMP_DYNAMIC_CORE_MAX
|
||||
thread_ptr -> tx_thread_smp_cores_allowed = ((ULONG) TX_THREAD_SMP_CORE_MASK);
|
||||
#else
|
||||
thread_ptr -> tx_thread_smp_cores_allowed = (((ULONG) 1) << _tx_thread_smp_max_cores) - 1;
|
||||
#endif
|
||||
|
||||
#ifdef TX_THREAD_SMP_ONLY_CORE_0_DEFAULT
|
||||
|
||||
/* Default thread creation such that core0 is the only allowed core for execution, i.e., bit 1 is set to exclude core1. */
|
||||
thread_ptr -> tx_thread_smp_cores_excluded = (TX_THREAD_SMP_CORE_MASK & 0xFFFFFFFE);
|
||||
thread_ptr -> tx_thread_smp_cores_allowed = 1;
|
||||
|
||||
/* Default the timers to run on core 0 as well. */
|
||||
thread_ptr -> tx_thread_timer.tx_timer_internal_smp_cores_excluded = (TX_THREAD_SMP_CORE_MASK & 0xFFFFFFFE);
|
||||
|
||||
/* Default the mapped to 0 too. */
|
||||
thread_ptr -> tx_thread_smp_core_mapped = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Calculate the end of the thread's stack area. */
|
||||
temp_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(stack_start);
|
||||
temp_ptr = (TX_UCHAR_POINTER_ADD(temp_ptr, (stack_size - ((ULONG) 1))));
|
||||
thread_ptr -> tx_thread_stack_end = TX_UCHAR_TO_VOID_POINTER_CONVERT(temp_ptr);
|
||||
#if TXM_MODULE_MEMORY_PROTECTION
|
||||
thread_ptr -> tx_thread_module_stack_end = thread_ptr -> tx_thread_stack_end;
|
||||
#endif
|
||||
thread_ptr -> tx_thread_priority = priority;
|
||||
thread_ptr -> tx_thread_user_priority = priority;
|
||||
thread_ptr -> tx_thread_time_slice = time_slice;
|
||||
thread_ptr -> tx_thread_new_time_slice = time_slice;
|
||||
thread_ptr -> tx_thread_inherit_priority = TX_MAX_PRIORITIES;
|
||||
|
||||
#endif /* TXM_MODULE_MEMORY_PROTECTION */
|
||||
|
||||
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
|
||||
/* Preemption-threshold is enabled, setup accordingly. */
|
||||
@@ -381,9 +398,9 @@ ULONG status;
|
||||
|
||||
/* Preemption-threshold specified. Since specific preemption-threshold is not supported,
|
||||
disable all preemption. */
|
||||
thread_ptr -> tx_thread_preempt_threshold = 0;
|
||||
thread_ptr -> tx_thread_user_preempt_threshold = 0;
|
||||
}
|
||||
thread_ptr -> tx_thread_preempt_threshold = ((UINT) 0);
|
||||
thread_ptr -> tx_thread_user_preempt_threshold = ((UINT) 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -399,6 +416,9 @@ ULONG status;
|
||||
/* Setup the necessary fields in the thread timer block. */
|
||||
TX_THREAD_CREATE_TIMEOUT_SETUP(thread_ptr)
|
||||
|
||||
/* Perform any additional thread setup activities for tool or user purpose. */
|
||||
TX_THREAD_CREATE_INTERNAL_EXTENSION(thread_ptr)
|
||||
|
||||
/* Setup pointer to the thread entry information structure, which will live at the top of each
|
||||
module thread's stack. This will allow the module thread entry function to avoid direct
|
||||
access to the actual thread control block. */
|
||||
@@ -420,9 +440,9 @@ ULONG status;
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
thread_entry_info -> txm_module_thread_entry_info_exit_notify = thread_ptr -> tx_thread_entry_exit_notify;
|
||||
#else
|
||||
#else /* TX_DISABLE_NOTIFY_CALLBACKS */
|
||||
thread_entry_info -> txm_module_thread_entry_info_exit_notify = TX_NULL;
|
||||
#endif
|
||||
#endif /* TX_DISABLE_NOTIFY_CALLBACKS */
|
||||
if (thread_ptr -> tx_thread_entry == module_instance -> txm_module_instance_start_thread_entry)
|
||||
thread_entry_info -> txm_module_thread_entry_info_start_thread = TX_TRUE;
|
||||
else
|
||||
@@ -457,7 +477,7 @@ ULONG status;
|
||||
|
||||
/* Place the thread on the list of created threads. First,
|
||||
check for an empty list. */
|
||||
if (_tx_thread_created_count++ == 0)
|
||||
if (_tx_thread_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* The created thread list is empty. Add thread to empty list. */
|
||||
@@ -478,14 +498,17 @@ ULONG status;
|
||||
|
||||
/* Setup this thread's created links. */
|
||||
thread_ptr -> tx_thread_created_previous = previous_thread;
|
||||
thread_ptr -> tx_thread_created_next = next_thread;
|
||||
thread_ptr -> tx_thread_created_next = next_thread;
|
||||
}
|
||||
|
||||
/* Increment the thread created count. */
|
||||
_tx_thread_created_count++;
|
||||
|
||||
/* If trace is enabled, register this object. */
|
||||
TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_THREAD, thread_ptr, name, stack_start, stack_size)
|
||||
TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_THREAD, thread_ptr, name_ptr, TX_POINTER_TO_ULONG_CONVERT(stack_start), stack_size)
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_CREATE, thread_ptr, priority, stack_start, stack_size, TX_TRACE_THREAD_EVENTS)
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_CREATE, thread_ptr, priority, TX_POINTER_TO_ULONG_CONVERT(stack_start), stack_size, TX_TRACE_THREAD_EVENTS)
|
||||
|
||||
/* Register thread in the thread array structure. */
|
||||
TX_EL_THREAD_REGISTER(thread_ptr)
|
||||
@@ -493,13 +516,131 @@ ULONG status;
|
||||
/* Log this kernel call. */
|
||||
TX_EL_THREAD_CREATE_INSERT
|
||||
|
||||
#ifdef TX_THREAD_SMP
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
#endif
|
||||
|
||||
/* Determine if an automatic start was requested. If so, call the resume
|
||||
thread function and then check for a preemption condition. */
|
||||
if (auto_start == TX_AUTO_START)
|
||||
{
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Perform any additional activities for tool or user purpose. */
|
||||
TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
#else
|
||||
|
||||
/* Restore previous interrupt posture. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Perform any additional activities for tool or user purpose. */
|
||||
TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
|
||||
/* Call the resume thread function to make this thread ready. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
|
||||
/* Disable interrupts again. */
|
||||
TX_DISABLE
|
||||
#endif
|
||||
|
||||
/* Determine if the execution list needs to be re-evaluated. */
|
||||
if (_tx_thread_smp_current_state_get() >= TX_INITIALIZE_IN_PROGRESS)
|
||||
{
|
||||
|
||||
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
|
||||
/* Clear the preemption bit maps, since nothing has yet run during initialization. */
|
||||
TX_MEMSET(_tx_thread_preempted_maps, 0, sizeof(_tx_thread_preempted_maps));
|
||||
#if TX_MAX_PRIORITIES > 32
|
||||
_tx_thread_preempted_map_active = ((ULONG) 0);
|
||||
#endif
|
||||
|
||||
/* Clear the entry in the preempted thread list. */
|
||||
_tx_thread_preemption_threshold_list[priority] = TX_NULL;
|
||||
#endif
|
||||
|
||||
/* Set the pointer to the thread currently with preemption-threshold set to NULL. */
|
||||
_tx_thread_preemption__threshold_scheduled = TX_NULL;
|
||||
|
||||
#ifdef TX_THREAD_SMP_DEBUG_ENABLE
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_thread_smp_debug_entry_insert(12, 0, thread_ptr);
|
||||
#endif
|
||||
|
||||
/* Get the core index. */
|
||||
core_index = TX_SMP_CORE_ID;
|
||||
|
||||
/* Call the rebalance routine. This routine maps cores and ready threads. */
|
||||
_tx_thread_smp_rebalance_execute_list(core_index);
|
||||
|
||||
#ifdef TX_THREAD_SMP_DEBUG_ENABLE
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_thread_smp_debug_entry_insert(13, 0, thread_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Perform any additional activities for tool or user purpose. */
|
||||
TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Perform any additional activities for tool or user purpose. */
|
||||
TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Re-enable preemption. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* TX_THREAD_SMP */
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
#endif
|
||||
|
||||
/* Determine if an automatic start was requested. If so, call the resume
|
||||
thread function and then check for a preemption condition. */
|
||||
if (auto_start == TX_AUTO_START)
|
||||
{
|
||||
|
||||
/* Determine if the create call is being called from initialization. */
|
||||
if (TX_THREAD_GET_SYSTEM_STATE() >= TX_INITIALIZE_IN_PROGRESS)
|
||||
{
|
||||
@@ -526,14 +667,13 @@ ULONG status;
|
||||
initialization is complete. */
|
||||
saved_thread_ptr -> tx_thread_preempt_threshold = saved_thread_ptr -> tx_thread_priority;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Simply set the saved thread pointer to NULL. */
|
||||
saved_thread_ptr = TX_NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
@@ -547,20 +687,15 @@ ULONG status;
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore previous interrupt posture. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Perform any additional activities for tool or user purpose. */
|
||||
TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
|
||||
/* Call the resume thread function to make this thread ready. */
|
||||
/* Call the resume thread function to make this thread ready. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
|
||||
/* Determine if the thread's preemption-threshold needs to be restored. */
|
||||
if (saved_thread_ptr != TX_NULL)
|
||||
@@ -569,15 +704,41 @@ ULONG status;
|
||||
/* Yes, restore the previous highest-priority thread's preemption-threshold. This
|
||||
can only happen if this routine is called from initialization. */
|
||||
saved_thread_ptr -> tx_thread_preempt_threshold = saved_threshold;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Interrupts are already restored, simply return success. */
|
||||
return(TX_SUCCESS);
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Perform any additional activities for tool or user purpose. */
|
||||
TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Perform any additional activities for tool or user purpose. */
|
||||
TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Re-enable preemption. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#endif /* TX_THREAD_SMP */
|
||||
|
||||
/* Return success. */
|
||||
return(TX_SUCCESS);
|
||||
|
||||
Reference in New Issue
Block a user