diff options
| author | Scott Larson <[email protected]> | 2020-08-07 16:56:45 -0700 |
|---|---|---|
| committer | Scott Larson <[email protected]> | 2020-08-07 16:56:45 -0700 |
| commit | 6f61053f2ac6cfa01a33b910401a61e63bca0972 (patch) | |
| tree | 7ba850077c3fb4d024c8f6d59609e94c6c627707 /common_modules/module_manager/src/txm_module_manager_stop.c | |
| parent | 49e3c27f3f140cd76147d85ccbb1eea31e09ee16 (diff) | |
add SMP, Modules, and more processor/tools releases
Diffstat (limited to 'common_modules/module_manager/src/txm_module_manager_stop.c')
| -rw-r--r-- | common_modules/module_manager/src/txm_module_manager_stop.c | 571 |
1 files changed, 571 insertions, 0 deletions
diff --git a/common_modules/module_manager/src/txm_module_manager_stop.c b/common_modules/module_manager/src/txm_module_manager_stop.c new file mode 100644 index 00000000..b9682a1d --- /dev/null +++ b/common_modules/module_manager/src/txm_module_manager_stop.c @@ -0,0 +1,571 @@ +/**************************************************************************/ +/* */ +/* 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_thread.h" +#include "tx_timer.h" +#include "tx_queue.h" +#include "tx_event_flags.h" +#include "tx_semaphore.h" +#include "tx_mutex.h" +#include "tx_block_pool.h" +#include "tx_byte_pool.h" +#include "txm_module.h" +#include "txm_module_manager_util.h" + +#ifdef TXM_MODULE_ENABLE_FILEX +extern UINT _txm_module_manager_filex_stop(TXM_MODULE_INSTANCE *module_instance); +#endif + +#ifdef TXM_MODULE_ENABLE_NETX +extern UINT _txm_module_manager_netx_stop(TXM_MODULE_INSTANCE *module_instance); +#endif + +#ifdef TXM_MODULE_ENABLE_NETXDUO +extern UINT _txm_module_manager_netxduo_stop(TXM_MODULE_INSTANCE *module_instance); +#endif + +#ifdef TXM_MODULE_ENABLE_GUIX +extern UINT _txm_module_manager_guix_stop(TXM_MODULE_INSTANCE *module_instance); +#endif + +#ifdef TXM_MODULE_ENABLE_USBX +extern UINT _txm_module_manager_usbx_stop(TXM_MODULE_INSTANCE *module_instance); +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_stop PORTABLE C */ +/* 6.0.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function stops execution of the specified module. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Module instance pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_block_pool_delete Block pool delete */ +/* _tx_byte_pool_delete Byte pool delete */ +/* _tx_event_flags_delete Event flags delete */ +/* _tx_mutex_delete Mutex delete */ +/* _tx_mutex_get Get protection mutex */ +/* _tx_mutex_put Release protection mutex */ +/* _tx_queue_delete Queue delete */ +/* _tx_semaphore_delete Semaphore delete */ +/* _tx_thread_delete Thread delete */ +/* _tx_thread_sleep Thread sleep */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* _tx_thread_terminate Thread terminate */ +/* _tx_timer_delete Timer delete */ +/* _txm_module_manager_callback_deactivate */ +/* Deactivate callback */ +/* _txm_module_manager_object_search Search for object in module's */ +/* allocated object list */ +/* _txm_module_manager_thread_create Module thread create */ +/* [_txm_module_manager_*_stop] Optional external component */ +/* stop functions */ +/* */ +/* CALLED BY */ +/* */ +/* Application code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 06-30-2020 Scott Larson Initial Version 6.0.1 */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_stop(TXM_MODULE_INSTANCE *module_instance) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr, *next_thread_ptr; +TX_TIMER *timer_ptr, *next_timer_ptr; +TX_QUEUE *queue_ptr, *next_queue_ptr; +TX_EVENT_FLAGS_GROUP *events_ptr, *next_events_ptr; +TX_SEMAPHORE *semaphore_ptr, *next_semaphore_ptr; +TX_MUTEX *mutex_ptr, *next_mutex_ptr; +TX_BLOCK_POOL *block_pool_ptr, *next_block_pool_ptr; +TX_BYTE_POOL *byte_pool_ptr, *next_byte_pool_ptr; +UCHAR created_by_module; +ULONG i; +TXM_MODULE_ALLOCATED_OBJECT *object_ptr; + + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Determine if this is a legal request. */ + + /* Is there a current thread? */ + if (thread_ptr == TX_NULL) + { + + /* Illegal caller of this service. */ + return(TX_CALLER_ERROR); + } + + /* Is the caller an ISR or Initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() != 0) + { + + /* Illegal caller of this service. */ + return(TX_CALLER_ERROR); + } + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Check for invalid caller of this function. First check for a calling thread. */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + return(TX_CALLER_ERROR); + } +#endif + + /* 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 instance is valid. */ + if (module_instance -> txm_module_instance_id != TXM_MODULE_ID) + { + + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Invalid module pointer. */ + return(TX_PTR_ERROR); + } + + /* Determine if the module instance is in the loaded state. */ + if (module_instance -> txm_module_instance_state != TXM_MODULE_STARTED) + { + + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Return error if the module is not ready. */ + return(TX_START_ERROR); + } + + /* Set the module state to indicate the module is stopping. */ + module_instance -> txm_module_instance_state = TXM_MODULE_STOPPING; + + /* This thread was previously used as the start thread. So first, make sure it is terminated and deleted before doing anything else. */ + _tx_thread_terminate(&(module_instance -> txm_module_instance_start_stop_thread)); + _tx_thread_delete(&(module_instance -> txm_module_instance_start_stop_thread)); + + /* Determine if there is a module stop function. */ + if (module_instance -> txm_module_instance_stop_thread_entry) + { + + /* Yes, there is a stop function. Build a thread for executing the module stop function. */ + + /* Create the module stop thread. */ + _txm_module_manager_thread_create(&(module_instance -> txm_module_instance_start_stop_thread), + "Module Stop Thread", + module_instance -> txm_module_instance_shell_entry_function, + module_instance -> txm_module_instance_stop_thread_entry, + module_instance -> txm_module_instance_application_module_id, + module_instance -> txm_module_instance_start_stop_stack_start_address, + module_instance -> txm_module_instance_start_stop_stack_size, + (UINT) module_instance -> txm_module_instance_start_stop_priority, + (UINT) module_instance -> txm_module_instance_start_stop_priority, + TXM_MODULE_TIME_SLICE, + TX_AUTO_START, + sizeof(TX_THREAD), + module_instance); + + /* Wait for the stop thread to complete. */ + i = 0; + while ((i < TXM_MODULE_TIMEOUT) && (module_instance -> txm_module_instance_start_stop_thread.tx_thread_state != TX_COMPLETED)) + { + + /* Sleep to let the module stop thread run. */ + _tx_thread_sleep(1); + + /* Increment the counter. */ + i++; + } + + /* At this point, we need to terminate and delete the stop thread. */ + _tx_thread_terminate(&(module_instance -> txm_module_instance_start_stop_thread)); + _tx_thread_delete(&(module_instance -> txm_module_instance_start_stop_thread)); + } + + /* Delete the module's callback thread and queue for the callback thread. */ + _tx_thread_terminate(&(module_instance -> txm_module_instance_callback_request_thread)); + _tx_thread_delete(&(module_instance -> txm_module_instance_callback_request_thread)); + _tx_queue_delete(&(module_instance -> txm_module_instance_callback_request_queue)); + + /* Disable interrupts. */ + TX_DISABLE + + /* Temporarily disable preemption. This will keep other threads from creating and deleting threads. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Determine if any external component stop functions have been registered and + if so, call them to cleanup any module objects in that component. */ + +#ifdef TXM_MODULE_ENABLE_FILEX + + /* Call the FileX stop function. */ + _txm_module_manager_filex_stop(module_instance); +#endif + +#ifdef TXM_MODULE_ENABLE_NETX + + /* Call the NetX stop function. */ + _txm_module_manager_netx_stop(module_instance); +#endif + +#ifdef TXM_MODULE_ENABLE_NETXDUO + + /* Call the NetX Duo stop function. */ + _txm_module_manager_netxduo_stop(module_instance); +#endif + +#ifdef TXM_MODULE_ENABLE_GUIX + + /* Call the GUIX stop function. */ + _txm_module_manager_guix_stop(module_instance); +#endif + +#ifdef TXM_MODULE_ENABLE_USBX + + /* Call the USBX stop function. */ + _txm_module_manager_usbx_stop(module_instance); +#endif + + /* Loop to delete any and all threads created by the module. */ + i = _tx_thread_created_count; + thread_ptr = _tx_thread_created_ptr; + while (i--) + { + + /* Pickup the next thread pointer. */ + next_thread_ptr = thread_ptr -> tx_thread_created_next; + + /* Determine if the thread control block is inside the module. */ + if ( (((CHAR *) thread_ptr) >= ((CHAR *) module_instance -> txm_module_instance_data_start)) && + (((CHAR *) thread_ptr) < ((CHAR *) module_instance -> txm_module_instance_data_end))) + { + + /* Terminate and delete this thread, since it is part of this module. */ + _tx_thread_terminate(thread_ptr); + _tx_thread_delete(thread_ptr); + } + + /* Is this thread part of the module? */ + else if (thread_ptr -> tx_thread_module_instance_ptr == module_instance) + { + + /* Terminate and delete this thread, since it is part of this module. */ + _tx_thread_terminate(thread_ptr); + _tx_thread_delete(thread_ptr); + } + + /* Move to next thread. */ + thread_ptr = next_thread_ptr; + } + + /* Loop to delete any and all timers created by the module. */ + i = _tx_timer_created_count; + timer_ptr = _tx_timer_created_ptr; + while (i--) + { + + /* Pickup the next timer pointer. */ + next_timer_ptr = timer_ptr -> tx_timer_created_next; + + /* Check if this module created this timer. */ + created_by_module = _txm_module_manager_created_object_check(module_instance, (VOID *) timer_ptr); + if (created_by_module == TX_TRUE) + { + + /* Delete this timer, since it is part of this module. */ + _tx_timer_delete(timer_ptr); + } + + /* Move to next timer. */ + timer_ptr = next_timer_ptr; + } + + /* Loop to delete any and all queues created by the module. */ + i = _tx_queue_created_count; + queue_ptr = _tx_queue_created_ptr; + while (i--) + { + + /* Pickup the next queue pointer. */ + next_queue_ptr = queue_ptr -> tx_queue_created_next; + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Determine if the queue callback function is associated with this module. */ + if ((queue_ptr -> tx_queue_module_instance == module_instance) && + (queue_ptr -> tx_queue_send_notify == _txm_module_manager_queue_notify_trampoline)) + { + + /* Clear the callback notification for this queue since it is no longer valid. */ + queue_ptr -> tx_queue_send_notify = TX_NULL; + } +#endif + + /* Check if this module created this queue. */ + created_by_module = _txm_module_manager_created_object_check(module_instance, (VOID *) queue_ptr); + if (created_by_module == TX_TRUE) + { + + /* Delete this queue, since it is part of this module. */ + _tx_queue_delete(queue_ptr); + } + + /* Move to next queue. */ + queue_ptr = next_queue_ptr; + } + + /* Loop to delete any and all event flag groups created by the module. */ + i = _tx_event_flags_created_count; + events_ptr = _tx_event_flags_created_ptr; + while (i--) + { + + /* Pickup the next event flags group pointer. */ + next_events_ptr = events_ptr -> tx_event_flags_group_created_next; + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Determine if the event flags callback function is associated with this module. */ + if ((events_ptr -> tx_event_flags_group_module_instance == module_instance) && + (events_ptr -> tx_event_flags_group_set_notify == _txm_module_manager_event_flags_notify_trampoline)) + { + + /* Clear the callback notification for this event flag group since it is no longer valid. */ + events_ptr -> tx_event_flags_group_set_notify = TX_NULL; + } +#endif + + /* Check if this module created this event flags. */ + created_by_module = _txm_module_manager_created_object_check(module_instance, (VOID *) events_ptr); + if (created_by_module == TX_TRUE) + { + + /* Delete this event flags group, since it is part of this module. */ + _tx_event_flags_delete(events_ptr); + } + + /* Move to next event flags group. */ + events_ptr = next_events_ptr; + } + + /* Loop to delete any and all semaphores created by the module. */ + i = _tx_semaphore_created_count; + semaphore_ptr = _tx_semaphore_created_ptr; + while (i--) + { + + /* Pickup the next semaphore pointer. */ + next_semaphore_ptr = semaphore_ptr -> tx_semaphore_created_next; + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Determine if the semaphore callback function is associated with this module. */ + if ((semaphore_ptr -> tx_semaphore_module_instance == module_instance) && + (semaphore_ptr -> tx_semaphore_put_notify == _txm_module_manager_semaphore_notify_trampoline)) + { + + /* Clear the callback notification for this semaphore since it is no longer valid. */ + semaphore_ptr -> tx_semaphore_put_notify = TX_NULL; + } +#endif + + /* Check if this module created this semaphore. */ + created_by_module = _txm_module_manager_created_object_check(module_instance, (VOID *) semaphore_ptr); + if (created_by_module == TX_TRUE) + { + + /* Delete this semaphore, since it is part of this module. */ + _tx_semaphore_delete(semaphore_ptr); + } + + /* Move to next semaphore. */ + semaphore_ptr = next_semaphore_ptr; + } + + /* Loop to delete any and all mutexes created by the module. */ + i = _tx_mutex_created_count; + mutex_ptr = _tx_mutex_created_ptr; + while (i--) + { + + /* Pickup the next mutex pointer. */ + next_mutex_ptr = mutex_ptr -> tx_mutex_created_next; + + /* Check if this module created this mutex. */ + created_by_module = _txm_module_manager_created_object_check(module_instance, (VOID *) mutex_ptr); + if (created_by_module == TX_TRUE) + { + + /* Delete this mutex, since it is part of this module. */ + _tx_mutex_delete(mutex_ptr); + } + + /* Move to next mutex. */ + mutex_ptr = next_mutex_ptr; + } + + /* Loop to delete any and all block pools created by the module. */ + i = _tx_block_pool_created_count; + block_pool_ptr = _tx_block_pool_created_ptr; + while (i--) + { + + /* Pickup the next block pool pointer. */ + next_block_pool_ptr = block_pool_ptr -> tx_block_pool_created_next; + + /* Check if this module created this block pool. */ + created_by_module = _txm_module_manager_created_object_check(module_instance, (VOID *) block_pool_ptr); + if (created_by_module == TX_TRUE) + { + + /* Delete this block pool, since it is part of this module. */ + _tx_block_pool_delete(block_pool_ptr); + } + + /* Move to next block pool. */ + block_pool_ptr = next_block_pool_ptr; + } + + /* Loop to delete any and all byte pools created by the module. */ + i = _tx_byte_pool_created_count; + byte_pool_ptr = _tx_byte_pool_created_ptr; + while (i--) + { + + /* Pickup the next byte pool pointer. */ + next_byte_pool_ptr = byte_pool_ptr -> tx_byte_pool_created_next; + + /* Check if this module created this byte pool. */ + created_by_module = _txm_module_manager_created_object_check(module_instance, (VOID *) byte_pool_ptr); + if (created_by_module == TX_TRUE) + { + + /* Delete this byte pool, since it is part of this module. */ + _tx_byte_pool_delete(byte_pool_ptr); + } + + /* Move to next byte pool. */ + byte_pool_ptr = next_byte_pool_ptr; + } + +#ifdef TX_ENABLE_EVENT_TRACE + /* Has trace been enabled? */ + if (_tx_trace_buffer_current_ptr != TX_NULL) + { + + /* Is the trace buffer located inside the module? */ + if ((ULONG) _tx_trace_header_ptr -> tx_trace_header_buffer_start_pointer >= (ULONG) module_instance -> txm_module_instance_data_start && + (ULONG) _tx_trace_header_ptr -> tx_trace_header_buffer_start_pointer < (ULONG) module_instance -> txm_module_instance_data_end) + { + _tx_trace_disable(); + } + } +#endif + + /* Delete the allocated objects for this module. */ + while (module_instance -> txm_module_instance_object_list_count--) + { + + /* Pickup the current object pointer. */ + object_ptr = module_instance -> txm_module_instance_object_list_head; + + /* Move the head pointer forward. */ + module_instance -> txm_module_instance_object_list_head = object_ptr -> txm_module_allocated_object_next; + + /* Release the object. */ + _tx_byte_release((VOID *) object_ptr); + } + + /* Set the allocated list head pointer to NULL. */ + module_instance -> txm_module_instance_object_list_head = TX_NULL; + + /* Disable interrupts. */ + TX_DISABLE + + /* Enable preemption again. */ + _tx_thread_preempt_disable--; + + /* Set the module state to indicate the module is stopped. */ + module_instance -> txm_module_instance_state = TXM_MODULE_STOPPED; + + /* Restore interrupts. */ + TX_RESTORE + + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* Return success. */ + return(TX_SUCCESS); +} + |
