generated from Template/H563ZI-HAL-CMake-Template
	开启 ThreadX
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Build and Upload Artifact / build and upload-artifact (push) Successful in 25m8s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Build and Upload Artifact / build and upload-artifact (push) Successful in 25m8s
				
			This commit is contained in:
		
							
								
								
									
										374
									
								
								Middlewares/ST/threadx/common/src/tx_block_allocate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										374
									
								
								Middlewares/ST/threadx/common/src/tx_block_allocate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,374 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Block Pool                                                          */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
| #include "tx_trace.h" | ||||
| #endif | ||||
| #include "tx_thread.h" | ||||
| #include "tx_block_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_block_allocate                                  PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function allocates a block from the specified memory block     */ | ||||
| /*    pool.                                                               */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                          Pointer to pool control block     */ | ||||
| /*    block_ptr                         Pointer to place allocated block  */ | ||||
| /*                                        pointer                         */ | ||||
| /*    wait_option                       Suspension option                 */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_suspend         Suspend thread                    */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| UINT                        status; | ||||
| TX_THREAD                   *thread_ptr; | ||||
| UCHAR                       *work_ptr; | ||||
| UCHAR                       *temp_ptr; | ||||
| UCHAR                       **next_block_ptr; | ||||
| UCHAR                       **return_ptr; | ||||
| UINT                        suspended_count; | ||||
| TX_THREAD                   *next_thread; | ||||
| TX_THREAD                   *previous_thread; | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
| TX_TRACE_BUFFER_ENTRY       *entry_ptr; | ||||
| ULONG                       time_stamp =  ((ULONG) 0); | ||||
| #endif | ||||
| #ifdef TX_ENABLE_EVENT_LOGGING | ||||
| UCHAR                       *log_entry_ptr; | ||||
| ULONG                       upper_tbu; | ||||
| ULONG                       lower_tbu; | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to get a block from the pool.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Increment the total allocations counter.  */ | ||||
|     _tx_block_pool_performance_allocate_count++; | ||||
|  | ||||
|     /* Increment the number of allocations on this pool.  */ | ||||
|     pool_ptr -> tx_block_pool_performance_allocate_count++; | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|     /* If trace is enabled, save the current event pointer.  */ | ||||
|     entry_ptr =  _tx_trace_buffer_current_ptr; | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_ALLOCATE, pool_ptr, 0, wait_option, pool_ptr -> tx_block_pool_available, TX_TRACE_BLOCK_POOL_EVENTS) | ||||
|  | ||||
|     /* Save the time stamp for later comparison to verify that | ||||
|        the event hasn't been overwritten by the time the allocate | ||||
|        call succeeds.  */ | ||||
|     if (entry_ptr != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         time_stamp =  entry_ptr -> tx_trace_buffer_entry_time_stamp; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_LOGGING | ||||
|     log_entry_ptr =  *(UCHAR **) _tx_el_current_event; | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_BLOCK_ALLOCATE_INSERT | ||||
|  | ||||
|     /* Store -1 in the third event slot.  */ | ||||
|     *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) =  (ULONG) -1; | ||||
|  | ||||
|     /* Save the time stamp for later comparison to verify that | ||||
|        the event hasn't been overwritten by the time the allocate | ||||
|        call succeeds.  */ | ||||
|     lower_tbu =  *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)); | ||||
|     upper_tbu =  *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)); | ||||
| #endif | ||||
|  | ||||
|     /* Determine if there is an available block.  */ | ||||
|     if (pool_ptr -> tx_block_pool_available != ((UINT) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Yes, a block is available.  Decrement the available count.  */ | ||||
|         pool_ptr -> tx_block_pool_available--; | ||||
|  | ||||
|         /* Pickup the current block pointer.  */ | ||||
|         work_ptr =  pool_ptr -> tx_block_pool_available_list; | ||||
|  | ||||
|         /* Return the first available block to the caller.  */ | ||||
|         temp_ptr =  TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *))); | ||||
|         return_ptr =  TX_INDIRECT_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr); | ||||
|         *return_ptr =  temp_ptr; | ||||
|  | ||||
|         /* Modify the available list to point at the next block in the pool. */ | ||||
|         next_block_ptr =  TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr); | ||||
|         pool_ptr -> tx_block_pool_available_list =  *next_block_ptr; | ||||
|  | ||||
|         /* Save the pool's address in the block for when it is released!  */ | ||||
|         temp_ptr =  TX_BLOCK_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr); | ||||
|         *next_block_ptr =  temp_ptr; | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|         /* Check that the event time stamp is unchanged.  A different | ||||
|            timestamp means that a later event wrote over the byte | ||||
|            allocate event.  In that case, do nothing here.  */ | ||||
|         if (entry_ptr != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Is the time stamp the same?  */ | ||||
|             if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) | ||||
|             { | ||||
|  | ||||
|                 /* Timestamp is the same, update the entry with the address.  */ | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|                 entry_ptr -> tx_trace_buffer_entry_info_2 =  TX_POINTER_TO_ULONG_CONVERT(*block_ptr); | ||||
| #else | ||||
|                 entry_ptr -> tx_trace_buffer_entry_information_field_2 =  TX_POINTER_TO_ULONG_CONVERT(*block_ptr); | ||||
| #endif | ||||
|             } | ||||
|         } | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_LOGGING | ||||
|         /* Store the address of the allocated block.  */ | ||||
|         *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) =  (ULONG) *block_ptr; | ||||
| #endif | ||||
|  | ||||
|         /* Set status to success.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Default the return pointer to NULL.  */ | ||||
|         return_ptr =   TX_INDIRECT_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr); | ||||
|         *return_ptr =  TX_NULL; | ||||
|  | ||||
|         /* Determine if the request specifies suspension.  */ | ||||
|         if (wait_option != TX_NO_WAIT) | ||||
|         { | ||||
|  | ||||
|             /* Determine if the preempt disable flag is non-zero.  */ | ||||
|             if (_tx_thread_preempt_disable != ((UINT) 0)) | ||||
|             { | ||||
|  | ||||
|                 /* Suspension is not allowed if the preempt disable flag is non-zero at this point, return error completion.  */ | ||||
|                 status =  TX_NO_MEMORY; | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Prepare for suspension of this thread.  */ | ||||
|  | ||||
| #ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                 /* Increment the total suspensions counter.  */ | ||||
|                 _tx_block_pool_performance_suspension_count++; | ||||
|  | ||||
|                 /* Increment the number of suspensions on this pool.  */ | ||||
|                 pool_ptr -> tx_block_pool_performance_suspension_count++; | ||||
| #endif | ||||
|  | ||||
|                 /* Pickup thread pointer.  */ | ||||
|                 TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
|                 /* Setup cleanup routine pointer.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_cleanup =  &(_tx_block_pool_cleanup); | ||||
|  | ||||
|                 /* Setup cleanup information, i.e. this pool control | ||||
|                    block.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_control_block =  (VOID *) pool_ptr; | ||||
|  | ||||
|                 /* Save the return block pointer address as well.  */ | ||||
|                 thread_ptr -> tx_thread_additional_suspend_info =  (VOID *) block_ptr; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                 /* Increment the suspension sequence number, which is used to identify | ||||
|                    this suspension event.  */ | ||||
|                 thread_ptr -> tx_thread_suspension_sequence++; | ||||
| #endif | ||||
|  | ||||
|                 /* Pickup the number of suspended threads.  */ | ||||
|                 suspended_count =  (pool_ptr -> tx_block_pool_suspended_count); | ||||
|  | ||||
|                 /* Increment the number of suspended threads.  */ | ||||
|                 (pool_ptr -> tx_block_pool_suspended_count)++; | ||||
|  | ||||
|                 /* Setup suspension list.  */ | ||||
|                 if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|                 { | ||||
|  | ||||
|                     /* No other threads are suspended.  Setup the head pointer and | ||||
|                        just setup this threads pointers to itself.  */ | ||||
|                     pool_ptr -> tx_block_pool_suspension_list =     thread_ptr; | ||||
|                     thread_ptr -> tx_thread_suspended_next =        thread_ptr; | ||||
|                     thread_ptr -> tx_thread_suspended_previous =    thread_ptr; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* This list is not NULL, add current thread to the end. */ | ||||
|                     next_thread =                                   pool_ptr -> tx_block_pool_suspension_list; | ||||
|                     thread_ptr -> tx_thread_suspended_next =        next_thread; | ||||
|                     previous_thread =                               next_thread -> tx_thread_suspended_previous; | ||||
|                     thread_ptr -> tx_thread_suspended_previous =    previous_thread; | ||||
|                     previous_thread -> tx_thread_suspended_next =   thread_ptr; | ||||
|                     next_thread -> tx_thread_suspended_previous =   thread_ptr; | ||||
|                 } | ||||
|  | ||||
|                 /* Set the state to suspended.  */ | ||||
|                 thread_ptr -> tx_thread_state =       TX_BLOCK_MEMORY; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                 /* Call actual non-interruptable thread suspension routine.  */ | ||||
|                 _tx_thread_system_ni_suspend(thread_ptr, wait_option); | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
| #else | ||||
|  | ||||
|                 /* Set the suspending flag.  */ | ||||
|                 thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|                 /* Setup the timeout period.  */ | ||||
|                 thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  wait_option; | ||||
|  | ||||
|                 /* Temporarily disable preemption.  */ | ||||
|                 _tx_thread_preempt_disable++; | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Call actual thread suspension routine.  */ | ||||
|                 _tx_thread_system_suspend(thread_ptr); | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|                 /* Check that the event time stamp is unchanged.  A different | ||||
|                    timestamp means that a later event wrote over the byte | ||||
|                    allocate event.  In that case, do nothing here.  */ | ||||
|                 if (entry_ptr != TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     /* Is the time-stamp the same?  */ | ||||
|                     if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) | ||||
|                     { | ||||
|  | ||||
|                         /* Timestamp is the same, update the entry with the address.  */ | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|                         entry_ptr -> tx_trace_buffer_entry_info_2 =  TX_POINTER_TO_ULONG_CONVERT(*block_ptr); | ||||
| #else | ||||
|                         entry_ptr -> tx_trace_buffer_entry_information_field_2 =  TX_POINTER_TO_ULONG_CONVERT(*block_ptr); | ||||
| #endif | ||||
|                     } | ||||
|                 } | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_LOGGING | ||||
|                 /* Check that the event time stamp is unchanged and the call is about | ||||
|                    to return success.  A different timestamp means that a later event | ||||
|                    wrote over the block allocate event.  A return value other than | ||||
|                    TX_SUCCESS indicates that no block was available. In those cases, | ||||
|                    do nothing here.  */ | ||||
|                 if (lower_tbu ==  *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) && | ||||
|                     upper_tbu ==  *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) && | ||||
|                     ((thread_ptr -> tx_thread_suspend_status) == TX_SUCCESS)) | ||||
|                 { | ||||
|  | ||||
|                     /* Store the address of the allocated block.  */ | ||||
|                     *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) =  (ULONG) *block_ptr; | ||||
|                 } | ||||
| #endif | ||||
|  | ||||
|                 /* Return the completion status.  */ | ||||
|                 status =  thread_ptr -> tx_thread_suspend_status; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Immediate return, return error completion.  */ | ||||
|             status =  TX_NO_MEMORY; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										215
									
								
								Middlewares/ST/threadx/common/src/tx_block_pool_cleanup.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								Middlewares/ST/threadx/common/src/tx_block_pool_cleanup.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,215 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Block Pool                                                          */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_block_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_block_pool_cleanup                              PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function processes block allocate timeout and thread terminate */ | ||||
| /*    actions that require the block pool data structures to be cleaned   */ | ||||
| /*    up.                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                        Pointer to suspended thread's     */ | ||||
| /*                                        control block                   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_timeout                Thread timeout processing         */ | ||||
| /*    _tx_thread_terminate              Thread terminate processing       */ | ||||
| /*    _tx_thread_wait_abort             Thread wait abort processing      */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_block_pool_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence) | ||||
| { | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
| #endif | ||||
|  | ||||
| TX_BLOCK_POOL       *pool_ptr; | ||||
| UINT                suspended_count; | ||||
| TX_THREAD           *next_thread; | ||||
| TX_THREAD           *previous_thread; | ||||
|  | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|     /* Disable interrupts to remove the suspended thread from the block pool.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Determine if the cleanup is still required.  */ | ||||
|     if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_block_pool_cleanup)) | ||||
|     { | ||||
|  | ||||
|         /* Check for valid suspension sequence.  */ | ||||
|         if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence) | ||||
|         { | ||||
|  | ||||
|             /* Setup pointer to block pool control block.  */ | ||||
|             pool_ptr =  TX_VOID_TO_BLOCK_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); | ||||
|  | ||||
|             /* Check for a NULL byte pool pointer.  */ | ||||
|             if (pool_ptr != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Check for valid pool ID.  */ | ||||
|                 if (pool_ptr -> tx_block_pool_id == TX_BLOCK_POOL_ID) | ||||
|                 { | ||||
|  | ||||
|                     /* Determine if there are any thread suspensions.  */ | ||||
|                     if (pool_ptr -> tx_block_pool_suspended_count != TX_NO_SUSPENSIONS) | ||||
|                     { | ||||
| #else | ||||
|  | ||||
|                         /* Setup pointer to block pool control block.  */ | ||||
|                         pool_ptr =  TX_VOID_TO_BLOCK_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); | ||||
| #endif | ||||
|  | ||||
|                         /* Yes, we still have thread suspension!  */ | ||||
|  | ||||
|                         /* Clear the suspension cleanup flag.  */ | ||||
|                         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|                         /* Decrement the suspended count.  */ | ||||
|                         pool_ptr -> tx_block_pool_suspended_count--; | ||||
|  | ||||
|                         /* Pickup the suspended count.  */ | ||||
|                         suspended_count =  pool_ptr -> tx_block_pool_suspended_count; | ||||
|  | ||||
|                         /* Remove the suspended thread from the list.  */ | ||||
|  | ||||
|                         /* See if this is the only suspended thread on the list.  */ | ||||
|                         if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|                         { | ||||
|  | ||||
|                             /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|                             /* Update the head pointer.  */ | ||||
|                             pool_ptr -> tx_block_pool_suspension_list =  TX_NULL; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* At least one more thread is on the same suspension list.  */ | ||||
|  | ||||
|                             /* Update the links of the adjacent threads.  */ | ||||
|                             next_thread =                                   thread_ptr -> tx_thread_suspended_next; | ||||
|                             previous_thread =                               thread_ptr -> tx_thread_suspended_previous; | ||||
|                             next_thread -> tx_thread_suspended_previous =   previous_thread; | ||||
|                             previous_thread -> tx_thread_suspended_next =   next_thread; | ||||
|  | ||||
|                             /* Determine if we need to update the head pointer.  */ | ||||
|                             if (pool_ptr -> tx_block_pool_suspension_list == thread_ptr) | ||||
|                             { | ||||
|  | ||||
|                                 /* Update the list head pointer.  */ | ||||
|                                 pool_ptr -> tx_block_pool_suspension_list =     next_thread; | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         /* Now we need to determine if this cleanup is from a terminate, timeout, | ||||
|                            or from a wait abort.  */ | ||||
|                         if (thread_ptr -> tx_thread_state == TX_BLOCK_MEMORY) | ||||
|                         { | ||||
|  | ||||
|                             /* Timeout condition and the thread still suspended on the block pool. | ||||
|                                Setup return error status and resume the thread.  */ | ||||
|  | ||||
| #ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                             /* Increment the total timeouts counter.  */ | ||||
|                             _tx_block_pool_performance_timeout_count++; | ||||
|  | ||||
|                             /* Increment the number of timeouts on this block pool.  */ | ||||
|                             pool_ptr -> tx_block_pool_performance_timeout_count++; | ||||
| #endif | ||||
|  | ||||
|                             /* Setup return status.  */ | ||||
|                             thread_ptr -> tx_thread_suspend_status =  TX_NO_MEMORY; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                             /* Resume the thread!  */ | ||||
|                             _tx_thread_system_ni_resume(thread_ptr); | ||||
| #else | ||||
|                             /* Temporarily disable preemption.  */ | ||||
|                             _tx_thread_preempt_disable++; | ||||
|  | ||||
|                             /* Restore interrupts.  */ | ||||
|                             TX_RESTORE | ||||
|  | ||||
|                             /* Resume the thread!  */ | ||||
|                             _tx_thread_system_resume(thread_ptr); | ||||
|  | ||||
|                             /* Disable interrupts.  */ | ||||
|                             TX_DISABLE | ||||
| #endif | ||||
|                         } | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										215
									
								
								Middlewares/ST/threadx/common/src/tx_block_pool_create.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								Middlewares/ST/threadx/common/src/tx_block_pool_create.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,215 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Block Pool                                                          */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_block_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_block_pool_create                               PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function creates a pool of fixed-size memory blocks in the     */ | ||||
| /*    specified memory area.                                              */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                          Pointer to pool control block     */ | ||||
| /*    name_ptr                          Pointer to block pool name        */ | ||||
| /*    block_size                        Number of bytes in each block     */ | ||||
| /*    pool_start                        Address of beginning of pool area */ | ||||
| /*    pool_size                         Number of bytes in the block pool */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, | ||||
|                     VOID *pool_start, ULONG pool_size) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| UINT                blocks; | ||||
| UINT                status; | ||||
| ULONG               total_blocks; | ||||
| UCHAR               *block_ptr; | ||||
| UCHAR               **block_link_ptr; | ||||
| UCHAR               *next_block_ptr; | ||||
| TX_BLOCK_POOL       *next_pool; | ||||
| TX_BLOCK_POOL       *previous_pool; | ||||
|  | ||||
|  | ||||
|     /* Initialize block pool control block to all zeros.  */ | ||||
|     TX_MEMSET(pool_ptr, 0, (sizeof(TX_BLOCK_POOL))); | ||||
|  | ||||
|     /* Round the block size up to something that is evenly divisible by | ||||
|        an ALIGN_TYPE (typically this is a 32-bit ULONG). This helps guarantee proper alignment.  */ | ||||
|     block_size =  (((block_size + (sizeof(ALIGN_TYPE))) - ((ALIGN_TYPE) 1))/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE)); | ||||
|  | ||||
|     /* Round the pool size down to something that is evenly divisible by | ||||
|        an ALIGN_TYPE (typically this is a 32-bit ULONG).  */ | ||||
|     pool_size =   (pool_size/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE)); | ||||
|  | ||||
|     /* Setup the basic block pool fields.  */ | ||||
|     pool_ptr -> tx_block_pool_name =             name_ptr; | ||||
|     pool_ptr -> tx_block_pool_start =            TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); | ||||
|     pool_ptr -> tx_block_pool_size =             pool_size; | ||||
|     pool_ptr -> tx_block_pool_block_size =       (UINT) block_size; | ||||
|  | ||||
|     /* Calculate the total number of blocks.  */ | ||||
|     total_blocks =  pool_size/(block_size + (sizeof(UCHAR *))); | ||||
|  | ||||
|     /* Walk through the pool area, setting up the available block list.  */ | ||||
|     blocks =            ((UINT) 0); | ||||
|     block_ptr =         TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); | ||||
|     next_block_ptr =    TX_UCHAR_POINTER_ADD(block_ptr, (block_size + (sizeof(UCHAR *)))); | ||||
|     while(blocks < (UINT) total_blocks) | ||||
|     { | ||||
|  | ||||
|         /* Yes, we have another block.  Increment the block count.  */ | ||||
|         blocks++; | ||||
|  | ||||
|         /* Setup the link to the next block.  */ | ||||
|         block_link_ptr =  TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr); | ||||
|         *block_link_ptr =  next_block_ptr; | ||||
|  | ||||
|         /* Advance to the next block.  */ | ||||
|         block_ptr =   next_block_ptr; | ||||
|  | ||||
|         /* Update the next block pointer.  */ | ||||
|         next_block_ptr =  TX_UCHAR_POINTER_ADD(block_ptr, (block_size + (sizeof(UCHAR *)))); | ||||
|     } | ||||
|  | ||||
|     /* Save the remaining information in the pool control block.  */ | ||||
|     pool_ptr -> tx_block_pool_available =  blocks; | ||||
|     pool_ptr -> tx_block_pool_total =      blocks; | ||||
|  | ||||
|     /* Quickly check to make sure at least one block is in the pool.  */ | ||||
|     if (blocks != ((UINT) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Backup to the last block in the pool.  */ | ||||
|         block_ptr =  TX_UCHAR_POINTER_SUB(block_ptr,(block_size + (sizeof(UCHAR *)))); | ||||
|  | ||||
|         /* Set the last block's forward pointer to NULL.  */ | ||||
|         block_link_ptr =  TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr); | ||||
|         *block_link_ptr =  TX_NULL; | ||||
|  | ||||
|         /* Setup the starting pool address.  */ | ||||
|         pool_ptr -> tx_block_pool_available_list =  TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); | ||||
|  | ||||
|         /* Disable interrupts to place the block pool on the created list.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* Setup the block pool ID to make it valid.  */ | ||||
|         pool_ptr -> tx_block_pool_id =  TX_BLOCK_POOL_ID; | ||||
|  | ||||
|         /* Place the block pool on the list of created block pools.  First, | ||||
|            check for an empty list.  */ | ||||
|         if (_tx_block_pool_created_count == TX_EMPTY) | ||||
|         { | ||||
|  | ||||
|             /* The created block pool list is empty.  Add block pool to empty list.  */ | ||||
|             _tx_block_pool_created_ptr =                  pool_ptr; | ||||
|             pool_ptr -> tx_block_pool_created_next =      pool_ptr; | ||||
|             pool_ptr -> tx_block_pool_created_previous =  pool_ptr; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* This list is not NULL, add to the end of the list.  */ | ||||
|             next_pool =      _tx_block_pool_created_ptr; | ||||
|             previous_pool =  next_pool -> tx_block_pool_created_previous; | ||||
|  | ||||
|             /* Place the new block pool in the list.  */ | ||||
|             next_pool -> tx_block_pool_created_previous =  pool_ptr; | ||||
|             previous_pool -> tx_block_pool_created_next =  pool_ptr; | ||||
|  | ||||
|             /* Setup this block pool's created links.  */ | ||||
|             pool_ptr -> tx_block_pool_created_previous =  previous_pool; | ||||
|             pool_ptr -> tx_block_pool_created_next =      next_pool; | ||||
|         } | ||||
|  | ||||
|         /* Increment the created count.  */ | ||||
|         _tx_block_pool_created_count++; | ||||
|  | ||||
|         /* Optional block pool create extended processing.  */ | ||||
|         TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr) | ||||
|  | ||||
|         /* If trace is enabled, register this object.  */ | ||||
|         TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_BLOCK_POOL, pool_ptr, name_ptr, pool_size, block_size) | ||||
|  | ||||
|         /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|         TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_CREATE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(pool_start), blocks, block_size, TX_TRACE_BLOCK_POOL_EVENTS) | ||||
|  | ||||
|         /* Log this kernel call.  */ | ||||
|         TX_EL_BLOCK_POOL_CREATE_INSERT | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Return successful status.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Not enough memory for one block, return appropriate error.  */ | ||||
|         status =  TX_SIZE_ERROR; | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										209
									
								
								Middlewares/ST/threadx/common/src/tx_block_pool_delete.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								Middlewares/ST/threadx/common/src/tx_block_pool_delete.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,209 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Block Pool                                                          */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_block_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_block_pool_delete                               PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function deletes the specified block pool.  All threads        */ | ||||
| /*    suspended on the block pool are resumed with the TX_DELETED status  */ | ||||
| /*    code.                                                               */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                          Pointer to pool control block     */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_block_pool_delete(TX_BLOCK_POOL *pool_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_THREAD       *next_thread; | ||||
| UINT            suspended_count; | ||||
| TX_BLOCK_POOL   *next_pool; | ||||
| TX_BLOCK_POOL   *previous_pool; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to remove the block pool from the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_DELETE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_BLOCK_POOL_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_BLOCK_POOL_DELETE_INSERT | ||||
|  | ||||
|     /* Optional block pool delete extended processing.  */ | ||||
|     TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr) | ||||
|  | ||||
|     /* If trace is enabled, unregister this object.  */ | ||||
|     TX_TRACE_OBJECT_UNREGISTER(pool_ptr) | ||||
|  | ||||
|     /* Clear the block pool ID to make it invalid.  */ | ||||
|     pool_ptr -> tx_block_pool_id =  TX_CLEAR_ID; | ||||
|  | ||||
|     /* Decrement the number of block pools.  */ | ||||
|     _tx_block_pool_created_count--; | ||||
|  | ||||
|     /* See if the block pool is the only one on the list.  */ | ||||
|     if (_tx_block_pool_created_count == TX_EMPTY) | ||||
|     { | ||||
|  | ||||
|         /* Only created block pool, just set the created list to NULL.  */ | ||||
|         _tx_block_pool_created_ptr =  TX_NULL; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Link-up the neighbors.  */ | ||||
|         next_pool =                                    pool_ptr -> tx_block_pool_created_next; | ||||
|         previous_pool =                                pool_ptr -> tx_block_pool_created_previous; | ||||
|         next_pool -> tx_block_pool_created_previous =  previous_pool; | ||||
|         previous_pool -> tx_block_pool_created_next =  next_pool; | ||||
|  | ||||
|         /* See if we have to update the created list head pointer.  */ | ||||
|         if (_tx_block_pool_created_ptr == pool_ptr) | ||||
|         { | ||||
|  | ||||
|             /* Yes, move the head pointer to the next link. */ | ||||
|             _tx_block_pool_created_ptr =  next_pool; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Temporarily disable preemption.  */ | ||||
|     _tx_thread_preempt_disable++; | ||||
|  | ||||
|     /* Pickup the suspension information.  */ | ||||
|     thread_ptr =                                 pool_ptr -> tx_block_pool_suspension_list; | ||||
|     pool_ptr -> tx_block_pool_suspension_list =  TX_NULL; | ||||
|     suspended_count =                            pool_ptr -> tx_block_pool_suspended_count; | ||||
|     pool_ptr -> tx_block_pool_suspended_count =  TX_NO_SUSPENSIONS; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Walk through the block pool suspension list to resume any and all threads suspended | ||||
|        on this block pool.  */ | ||||
|     while (suspended_count != TX_NO_SUSPENSIONS) | ||||
|     { | ||||
|  | ||||
|         /* Decrement the suspension count.  */ | ||||
|         suspended_count--; | ||||
|  | ||||
|         /* Lockout interrupts.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* Clear the cleanup pointer, this prevents the timeout from doing | ||||
|            anything.  */ | ||||
|         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|         /* Set the return status in the thread to TX_DELETED.  */ | ||||
|         thread_ptr -> tx_thread_suspend_status =  TX_DELETED; | ||||
|  | ||||
|         /* Move the thread pointer ahead.  */ | ||||
|         next_thread =  thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Resume the thread!  */ | ||||
|         _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #else | ||||
|  | ||||
|         /* Temporarily disable preemption again.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Resume the thread.  */ | ||||
|         _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|         /* Move to next thread.  */ | ||||
|         thread_ptr =  next_thread; | ||||
|     } | ||||
|  | ||||
|     /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h.  */ | ||||
|     TX_BLOCK_POOL_DELETE_PORT_COMPLETION(pool_ptr) | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Release previous preempt disable.  */ | ||||
|     _tx_thread_preempt_disable--; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Check for preemption.  */ | ||||
|     _tx_thread_system_preempt_check(); | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										148
									
								
								Middlewares/ST/threadx/common/src/tx_block_pool_info_get.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								Middlewares/ST/threadx/common/src/tx_block_pool_info_get.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Block Memory                                                        */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_block_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_block_pool_info_get                             PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function retrieves information from the specified block pool.  */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                          Pointer to block pool control blk */ | ||||
| /*    name                              Destination for the pool name     */ | ||||
| /*    available_blocks                  Number of free blocks in pool     */ | ||||
| /*    total_blocks                      Total number of blocks in pool    */ | ||||
| /*    first_suspended                   Destination for pointer of first  */ | ||||
| /*                                        thread suspended on block pool  */ | ||||
| /*    suspended_count                   Destination for suspended count   */ | ||||
| /*    next_pool                         Destination for pointer to next   */ | ||||
| /*                                        block pool on the created list  */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, | ||||
|                     ULONG *total_blocks, TX_THREAD **first_suspended, | ||||
|                     ULONG *suspended_count, TX_BLOCK_POOL **next_pool) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_INFO_GET, pool_ptr, 0, 0, 0, TX_TRACE_BLOCK_POOL_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_BLOCK_POOL_INFO_GET_INSERT | ||||
|  | ||||
|     /* Retrieve all the pertinent information and return it in the supplied | ||||
|        destinations.  */ | ||||
|  | ||||
|     /* Retrieve the name of the block pool.  */ | ||||
|     if (name != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *name =  pool_ptr -> tx_block_pool_name; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the number of available blocks in the block pool.  */ | ||||
|     if (available_blocks != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *available_blocks =  (ULONG) pool_ptr -> tx_block_pool_available; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the total number of blocks in the block pool.  */ | ||||
|     if (total_blocks != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *total_blocks =  (ULONG) pool_ptr -> tx_block_pool_total; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the first thread suspended on this block pool.  */ | ||||
|     if (first_suspended != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *first_suspended =  pool_ptr -> tx_block_pool_suspension_list; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the number of threads suspended on this block pool.  */ | ||||
|     if (suspended_count != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *suspended_count =  (ULONG) pool_ptr -> tx_block_pool_suspended_count; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the pointer to the next block pool created.  */ | ||||
|     if (next_pool != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *next_pool =  pool_ptr -> tx_block_pool_created_next; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										133
									
								
								Middlewares/ST/threadx/common/src/tx_block_pool_initialize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								Middlewares/ST/threadx/common/src/tx_block_pool_initialize.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Block Pool                                                          */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_block_pool.h" | ||||
|  | ||||
|  | ||||
| #ifndef TX_INLINE_INITIALIZATION | ||||
|  | ||||
| /* Locate block pool component data in this file.  */ | ||||
|  | ||||
| /* Define the head pointer of the created block pool list.  */ | ||||
|  | ||||
| TX_BLOCK_POOL *  _tx_block_pool_created_ptr; | ||||
|  | ||||
|  | ||||
| /* Define the variable that holds the number of created block pools. */ | ||||
|  | ||||
| ULONG            _tx_block_pool_created_count; | ||||
|  | ||||
|  | ||||
| #ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
| /* Define the total number of block allocates.  */ | ||||
|  | ||||
| ULONG            _tx_block_pool_performance_allocate_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of block releases.  */ | ||||
|  | ||||
| ULONG            _tx_block_pool_performance_release_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of block pool suspensions.  */ | ||||
|  | ||||
| ULONG            _tx_block_pool_performance_suspension_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of block pool timeouts.  */ | ||||
|  | ||||
| ULONG            _tx_block_pool_performance_timeout_count; | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_block pool_initialize                           PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function initializes the various control data structures for   */ | ||||
| /*    the block pool component.                                           */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_initialize_high_level         High level initialization         */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            opt out of function when    */ | ||||
| /*                                            TX_INLINE_INITIALIZATION is */ | ||||
| /*                                            defined,                    */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_block_pool_initialize(VOID) | ||||
| { | ||||
|  | ||||
| #ifndef TX_DISABLE_REDUNDANT_CLEARING | ||||
|  | ||||
|     /* Initialize the head pointer of the created block pools list and the | ||||
|        number of block pools created.  */ | ||||
|     _tx_block_pool_created_ptr =        TX_NULL; | ||||
|     _tx_block_pool_created_count =      TX_EMPTY; | ||||
|  | ||||
| #ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Initialize block pool performance counters.  */ | ||||
|     _tx_block_pool_performance_allocate_count =    ((ULONG) 0); | ||||
|     _tx_block_pool_performance_release_count =     ((ULONG) 0); | ||||
|     _tx_block_pool_performance_suspension_count =  ((ULONG) 0); | ||||
|     _tx_block_pool_performance_timeout_count =     ((ULONG) 0); | ||||
| #endif | ||||
| #endif | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										251
									
								
								Middlewares/ST/threadx/common/src/tx_block_pool_prioritize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										251
									
								
								Middlewares/ST/threadx/common/src/tx_block_pool_prioritize.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,251 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Block Pool                                                          */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_block_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_block_pool_prioritize                           PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function places the highest priority suspended thread at the   */ | ||||
| /*    front of the suspension list.  All other threads remain in the same */ | ||||
| /*    FIFO suspension order.                                              */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                         Pointer to pool control block      */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_THREAD       *priority_thread_ptr; | ||||
| TX_THREAD       *head_ptr; | ||||
| UINT            suspended_count; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| UINT            list_changed; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_PRIORITIZE, pool_ptr, pool_ptr -> tx_block_pool_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_BLOCK_POOL_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_BLOCK_POOL_PRIORITIZE_INSERT | ||||
|  | ||||
|     /* Pickup the suspended count.  */ | ||||
|     suspended_count =  pool_ptr -> tx_block_pool_suspended_count; | ||||
|  | ||||
|     /* Determine if there are fewer than 2 suspended threads.  */ | ||||
|     if (suspended_count < ((UINT) 2)) | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|  | ||||
|     /* Determine if there how many threads are suspended on this block memory pool.  */ | ||||
|     else if (suspended_count == ((UINT) 2)) | ||||
|     { | ||||
|  | ||||
|         /* Pickup the head pointer and the next pointer.  */ | ||||
|         head_ptr =  pool_ptr -> tx_block_pool_suspension_list; | ||||
|         next_thread =  head_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|         /* Determine if the next suspended thread has a higher priority.  */ | ||||
|         if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority)) | ||||
|         { | ||||
|  | ||||
|             /* Yes, move the list head to the next thread.  */ | ||||
|             pool_ptr -> tx_block_pool_suspension_list =  next_thread; | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Remember the suspension count and head pointer.  */ | ||||
|         head_ptr =   pool_ptr -> tx_block_pool_suspension_list; | ||||
|  | ||||
|         /* Default the highest priority thread to the thread at the front of the list.  */ | ||||
|         priority_thread_ptr =  head_ptr; | ||||
|  | ||||
|         /* Setup search pointer.  */ | ||||
|         thread_ptr =  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|         /* Disable preemption.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Set the list changed flag to false.  */ | ||||
|         list_changed =  TX_FALSE; | ||||
|  | ||||
|         /* Search through the list to find the highest priority thread.  */ | ||||
|         do | ||||
|         { | ||||
|  | ||||
|             /* Is the current thread higher priority?  */ | ||||
|             if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, remember that this thread is the highest priority.  */ | ||||
|                 priority_thread_ptr =  thread_ptr; | ||||
|             } | ||||
|  | ||||
|             /* Restore interrupts temporarily.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Disable interrupts again.  */ | ||||
|             TX_DISABLE | ||||
|  | ||||
|             /* Determine if any changes to the list have occurred while | ||||
|                interrupts were enabled.  */ | ||||
|  | ||||
|             /* Is the list head the same?  */ | ||||
|             if (head_ptr != pool_ptr -> tx_block_pool_suspension_list) | ||||
|             { | ||||
|  | ||||
|                 /* The list head has changed, set the list changed flag.  */ | ||||
|                 list_changed =  TX_TRUE; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Is the suspended count the same?  */ | ||||
|                 if (suspended_count != pool_ptr -> tx_block_pool_suspended_count) | ||||
|                 { | ||||
|  | ||||
|                     /* The list head has changed, set the list changed flag.  */ | ||||
|                     list_changed =  TX_TRUE; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             /* Determine if the list has changed.  */ | ||||
|             if (list_changed == TX_FALSE) | ||||
|             { | ||||
|  | ||||
|                 /* Move the thread pointer to the next thread.  */ | ||||
|                 thread_ptr =  thread_ptr -> tx_thread_suspended_next; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Remember the suspension count and head pointer.  */ | ||||
|                 head_ptr =   pool_ptr -> tx_block_pool_suspension_list; | ||||
|                 suspended_count =  pool_ptr -> tx_block_pool_suspended_count; | ||||
|  | ||||
|                 /* Default the highest priority thread to the thread at the front of the list.  */ | ||||
|                 priority_thread_ptr =  head_ptr; | ||||
|  | ||||
|                 /* Setup search pointer.  */ | ||||
|                 thread_ptr =  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|                 /* Reset the list changed flag.  */ | ||||
|                 list_changed =  TX_FALSE; | ||||
|             } | ||||
|  | ||||
|         } while (thread_ptr != head_ptr); | ||||
|  | ||||
|         /* Release preemption.  */ | ||||
|         _tx_thread_preempt_disable--; | ||||
|  | ||||
|         /* Now determine if the highest priority thread is at the front | ||||
|            of the list.  */ | ||||
|         if (priority_thread_ptr != head_ptr) | ||||
|         { | ||||
|  | ||||
|             /* No, we need to move the highest priority suspended thread to the | ||||
|                front of the list.  */ | ||||
|  | ||||
|             /* First, remove the highest priority thread by updating the | ||||
|                adjacent suspended threads.  */ | ||||
|             next_thread =                                  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|             previous_thread =                              priority_thread_ptr -> tx_thread_suspended_previous; | ||||
|             next_thread -> tx_thread_suspended_previous =  previous_thread; | ||||
|             previous_thread -> tx_thread_suspended_next =  next_thread; | ||||
|  | ||||
|             /* Now, link the highest priority thread at the front of the list.  */ | ||||
|             previous_thread =                                      head_ptr -> tx_thread_suspended_previous; | ||||
|             priority_thread_ptr -> tx_thread_suspended_next =      head_ptr; | ||||
|             priority_thread_ptr -> tx_thread_suspended_previous =  previous_thread; | ||||
|             previous_thread -> tx_thread_suspended_next =          priority_thread_ptr; | ||||
|             head_ptr -> tx_thread_suspended_previous =             priority_thread_ptr; | ||||
|  | ||||
|             /* Move the list head pointer to the highest priority suspended thread.  */ | ||||
|             pool_ptr -> tx_block_pool_suspension_list =  priority_thread_ptr; | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Check for preemption.  */ | ||||
|         _tx_thread_system_preempt_check(); | ||||
|     } | ||||
|  | ||||
|     /* Return successful status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										206
									
								
								Middlewares/ST/threadx/common/src/tx_block_release.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								Middlewares/ST/threadx/common/src/tx_block_release.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,206 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Block Pool                                                          */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_block_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_block_release                                   PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function returns a previously allocated block to its           */ | ||||
| /*    associated memory block pool.                                       */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    block_ptr                         Pointer to memory block           */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_block_release(VOID *block_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_BLOCK_POOL       *pool_ptr; | ||||
| TX_THREAD           *thread_ptr; | ||||
| UCHAR               *work_ptr; | ||||
| UCHAR               **return_block_ptr; | ||||
| UCHAR               **next_block_ptr; | ||||
| UINT                suspended_count; | ||||
| TX_THREAD           *next_thread; | ||||
| TX_THREAD           *previous_thread; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to put this block back in the pool.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Pickup the pool pointer which is just previous to the starting | ||||
|        address of the block that the caller sees.  */ | ||||
|     work_ptr =        TX_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr); | ||||
|     work_ptr =        TX_UCHAR_POINTER_SUB(work_ptr, (sizeof(UCHAR *))); | ||||
|     next_block_ptr =  TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr); | ||||
|     pool_ptr =        TX_UCHAR_TO_BLOCK_POOL_POINTER_CONVERT((*next_block_ptr)); | ||||
|  | ||||
| #ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Increment the total releases counter.  */ | ||||
|     _tx_block_pool_performance_release_count++; | ||||
|  | ||||
|     /* Increment the number of releases on this pool.  */ | ||||
|     pool_ptr -> tx_block_pool_performance_release_count++; | ||||
| #endif | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_RELEASE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(block_ptr), pool_ptr -> tx_block_pool_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&work_ptr), TX_TRACE_BLOCK_POOL_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_BLOCK_RELEASE_INSERT | ||||
|  | ||||
|     /* Determine if there are any threads suspended on the block pool.  */ | ||||
|     thread_ptr =  pool_ptr -> tx_block_pool_suspension_list; | ||||
|     if (thread_ptr != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Remove the suspended thread from the list.  */ | ||||
|  | ||||
|         /* Decrement the number of threads suspended.  */ | ||||
|         (pool_ptr -> tx_block_pool_suspended_count)--; | ||||
|  | ||||
|         /* Pickup the suspended count.  */ | ||||
|         suspended_count =  (pool_ptr -> tx_block_pool_suspended_count); | ||||
|  | ||||
|         /* See if this is the only suspended thread on the list.  */ | ||||
|         if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|         { | ||||
|  | ||||
|             /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|             /* Update the head pointer.  */ | ||||
|             pool_ptr -> tx_block_pool_suspension_list =  TX_NULL; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* At least one more thread is on the same expiration list.  */ | ||||
|  | ||||
|             /* Update the list head pointer.  */ | ||||
|             next_thread =                                thread_ptr -> tx_thread_suspended_next; | ||||
|             pool_ptr -> tx_block_pool_suspension_list =  next_thread; | ||||
|  | ||||
|             /* Update the links of the adjacent threads.  */ | ||||
|             previous_thread =                              thread_ptr -> tx_thread_suspended_previous; | ||||
|             next_thread -> tx_thread_suspended_previous =  previous_thread; | ||||
|             previous_thread -> tx_thread_suspended_next =  next_thread; | ||||
|         } | ||||
|  | ||||
|         /* Prepare for resumption of the first thread.  */ | ||||
|  | ||||
|         /* Clear cleanup routine to avoid timeout.  */ | ||||
|         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|         /* Return this block pointer to the suspended thread waiting for | ||||
|            a block.  */ | ||||
|         return_block_ptr =  TX_VOID_TO_INDIRECT_UCHAR_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info); | ||||
|         work_ptr =          TX_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr); | ||||
|         *return_block_ptr =  work_ptr; | ||||
|  | ||||
|         /* Put return status into the thread control block.  */ | ||||
|         thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Resume the thread!  */ | ||||
|         _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #else | ||||
|  | ||||
|         /* Temporarily disable preemption.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Resume thread.  */ | ||||
|         _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* No thread is suspended for a memory block.  */ | ||||
|  | ||||
|         /* Put the block back in the available list.  */ | ||||
|         *next_block_ptr =  pool_ptr -> tx_block_pool_available_list; | ||||
|  | ||||
|         /* Adjust the head pointer.  */ | ||||
|         pool_ptr -> tx_block_pool_available_list =  work_ptr; | ||||
|  | ||||
|         /* Increment the count of available blocks.  */ | ||||
|         pool_ptr -> tx_block_pool_available++; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|  | ||||
|     /* Return successful completion status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										411
									
								
								Middlewares/ST/threadx/common/src/tx_byte_allocate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										411
									
								
								Middlewares/ST/threadx/common/src/tx_byte_allocate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,411 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Byte Memory                                                         */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
| #include "tx_trace.h" | ||||
| #endif | ||||
| #include "tx_thread.h" | ||||
| #include "tx_byte_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_byte_allocate                                   PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function allocates bytes from the specified memory byte        */ | ||||
| /*    pool.                                                               */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                          Pointer to pool control block     */ | ||||
| /*    memory_ptr                        Pointer to place allocated bytes  */ | ||||
| /*                                        pointer                         */ | ||||
| /*    memory_size                       Number of bytes to allocate       */ | ||||
| /*    wait_option                       Suspension option                 */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_suspend         Suspend thread service            */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*    _tx_byte_pool_search              Search byte pool for memory       */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size,  ULONG wait_option) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| UINT                        status; | ||||
| TX_THREAD                   *thread_ptr; | ||||
| UCHAR                       *work_ptr; | ||||
| UINT                        suspended_count; | ||||
| TX_THREAD                   *next_thread; | ||||
| TX_THREAD                   *previous_thread; | ||||
| UINT                        finished; | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
| TX_TRACE_BUFFER_ENTRY       *entry_ptr; | ||||
| ULONG                       time_stamp =  ((ULONG) 0); | ||||
| #endif | ||||
| #ifdef TX_ENABLE_EVENT_LOGGING | ||||
| UCHAR                       *log_entry_ptr; | ||||
| ULONG                       upper_tbu; | ||||
| ULONG                       lower_tbu; | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     /* Round the memory size up to the next size that is evenly divisible by | ||||
|        an ALIGN_TYPE (this is typically a 32-bit ULONG).  This guarantees proper alignment.  */ | ||||
|     memory_size = (((memory_size + (sizeof(ALIGN_TYPE)))-((ALIGN_TYPE) 1))/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE)); | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Pickup thread pointer.  */ | ||||
|     TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
| #ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Increment the total allocations counter.  */ | ||||
|     _tx_byte_pool_performance_allocate_count++; | ||||
|  | ||||
|     /* Increment the number of allocations on this pool.  */ | ||||
|     pool_ptr -> tx_byte_pool_performance_allocate_count++; | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|     /* If trace is enabled, save the current event pointer.  */ | ||||
|     entry_ptr =  _tx_trace_buffer_current_ptr; | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_ALLOCATE, pool_ptr, 0, memory_size, wait_option, TX_TRACE_BYTE_POOL_EVENTS) | ||||
|  | ||||
|     /* Save the time stamp for later comparison to verify that | ||||
|        the event hasn't been overwritten by the time the allocate | ||||
|        call succeeds.  */ | ||||
|     if (entry_ptr != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         time_stamp =  entry_ptr -> tx_trace_buffer_entry_time_stamp; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_LOGGING | ||||
|     log_entry_ptr =  *(UCHAR **) _tx_el_current_event; | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_BYTE_ALLOCATE_INSERT | ||||
|  | ||||
|     /* Store -1 in the fourth event slot.  */ | ||||
|     *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) =  (ULONG) -1; | ||||
|  | ||||
|     /* Save the time stamp for later comparison to verify that | ||||
|        the event hasn't been overwritten by the time the allocate | ||||
|        call succeeds.  */ | ||||
|     lower_tbu =  *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)); | ||||
|     upper_tbu =  *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)); | ||||
| #endif | ||||
|  | ||||
|     /* Set the search finished flag to false.  */ | ||||
|     finished =  TX_FALSE; | ||||
|  | ||||
|     /* Loop to handle cases where the owner of the pool changed.  */ | ||||
|     do | ||||
|     { | ||||
|  | ||||
|         /* Indicate that this thread is the current owner.  */ | ||||
|         pool_ptr -> tx_byte_pool_owner =  thread_ptr; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* At this point, the executing thread owns the pool and can perform a search | ||||
|            for free memory.  */ | ||||
|         work_ptr =  _tx_byte_pool_search(pool_ptr, memory_size); | ||||
|  | ||||
|         /* Optional processing extension.  */ | ||||
|         TX_BYTE_ALLOCATE_EXTENSION | ||||
|  | ||||
|         /* Lockout interrupts.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* Determine if we are finished.  */ | ||||
|         if (work_ptr != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Yes, we have found a block the search is finished.  */ | ||||
|             finished =  TX_TRUE; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* No block was found, does this thread still own the pool?  */ | ||||
|             if (pool_ptr -> tx_byte_pool_owner == thread_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, then we have looked through the entire pool and haven't found the memory.  */ | ||||
|                 finished =  TX_TRUE; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     } while (finished == TX_FALSE); | ||||
|  | ||||
|     /* Copy the pointer into the return destination.  */ | ||||
|     *memory_ptr =  (VOID *) work_ptr; | ||||
|  | ||||
|     /* Determine if memory was found.  */ | ||||
|     if (work_ptr != TX_NULL) | ||||
|     { | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|         /* Check that the event time stamp is unchanged.  A different | ||||
|            timestamp means that a later event wrote over the byte | ||||
|            allocate event.  In that case, do nothing here.  */ | ||||
|         if (entry_ptr != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Is the timestamp the same?  */ | ||||
|             if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) | ||||
|             { | ||||
|  | ||||
|                 /* Timestamp is the same, update the entry with the address.  */ | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|                 entry_ptr -> tx_trace_buffer_entry_info_2 =  TX_POINTER_TO_ULONG_CONVERT(*memory_ptr); | ||||
| #else | ||||
|                 entry_ptr -> tx_trace_buffer_entry_information_field_2 =  TX_POINTER_TO_ULONG_CONVERT(*memory_ptr); | ||||
| #endif | ||||
|             } | ||||
|         } | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_LOGGING | ||||
|         /* Check that the event time stamp is unchanged.  A different | ||||
|            timestamp means that a later event wrote over the byte | ||||
|            allocate event.  In that case, do nothing here.  */ | ||||
|         if (lower_tbu ==  *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) && | ||||
|             upper_tbu ==  *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET))) | ||||
|         { | ||||
|             /* Store the address of the allocated fragment.  */ | ||||
|             *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) =  (ULONG) *memory_ptr; | ||||
|         } | ||||
| #endif | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Set the status to success.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* No memory of sufficient size was found...  */ | ||||
|  | ||||
|         /* Determine if the request specifies suspension.  */ | ||||
|         if (wait_option != TX_NO_WAIT) | ||||
|         { | ||||
|  | ||||
|             /* Determine if the preempt disable flag is non-zero.  */ | ||||
|             if (_tx_thread_preempt_disable != ((UINT) 0)) | ||||
|             { | ||||
|  | ||||
|                 /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion.  */ | ||||
|                 status =  TX_NO_MEMORY; | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Prepare for suspension of this thread.  */ | ||||
|  | ||||
| #ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                 /* Increment the total suspensions counter.  */ | ||||
|                 _tx_byte_pool_performance_suspension_count++; | ||||
|  | ||||
|                 /* Increment the number of suspensions on this pool.  */ | ||||
|                 pool_ptr -> tx_byte_pool_performance_suspension_count++; | ||||
| #endif | ||||
|  | ||||
|                 /* Setup cleanup routine pointer.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_cleanup =  &(_tx_byte_pool_cleanup); | ||||
|  | ||||
|                 /* Setup cleanup information, i.e. this pool control | ||||
|                    block.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_control_block =  (VOID *) pool_ptr; | ||||
|  | ||||
|                 /* Save the return memory pointer address as well.  */ | ||||
|                 thread_ptr -> tx_thread_additional_suspend_info =  (VOID *) memory_ptr; | ||||
|  | ||||
|                 /* Save the byte size requested.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_info =  memory_size; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                 /* Increment the suspension sequence number, which is used to identify | ||||
|                    this suspension event.  */ | ||||
|                 thread_ptr -> tx_thread_suspension_sequence++; | ||||
| #endif | ||||
|  | ||||
|                 /* Pickup the number of suspended threads.  */ | ||||
|                 suspended_count =  pool_ptr -> tx_byte_pool_suspended_count; | ||||
|  | ||||
|                 /* Increment the suspension count.  */ | ||||
|                 (pool_ptr -> tx_byte_pool_suspended_count)++; | ||||
|  | ||||
|                 /* Setup suspension list.  */ | ||||
|                 if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|                 { | ||||
|  | ||||
|                     /* No other threads are suspended.  Setup the head pointer and | ||||
|                        just setup this threads pointers to itself.  */ | ||||
|                     pool_ptr -> tx_byte_pool_suspension_list =      thread_ptr; | ||||
|                     thread_ptr -> tx_thread_suspended_next =        thread_ptr; | ||||
|                     thread_ptr -> tx_thread_suspended_previous =    thread_ptr; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* This list is not NULL, add current thread to the end. */ | ||||
|                     next_thread =                                   pool_ptr -> tx_byte_pool_suspension_list; | ||||
|                     thread_ptr -> tx_thread_suspended_next =        next_thread; | ||||
|                     previous_thread =                               next_thread -> tx_thread_suspended_previous; | ||||
|                     thread_ptr -> tx_thread_suspended_previous =    previous_thread; | ||||
|                     previous_thread -> tx_thread_suspended_next =   thread_ptr; | ||||
|                     next_thread -> tx_thread_suspended_previous =   thread_ptr; | ||||
|                 } | ||||
|  | ||||
|                 /* Set the state to suspended.  */ | ||||
|                 thread_ptr -> tx_thread_state =       TX_BYTE_MEMORY; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                 /* Call actual non-interruptable thread suspension routine.  */ | ||||
|                 _tx_thread_system_ni_suspend(thread_ptr, wait_option); | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
| #else | ||||
|  | ||||
|                 /* Set the suspending flag.  */ | ||||
|                 thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|                 /* Setup the timeout period.  */ | ||||
|                 thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  wait_option; | ||||
|  | ||||
|                 /* Temporarily disable preemption.  */ | ||||
|                 _tx_thread_preempt_disable++; | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Call actual thread suspension routine.  */ | ||||
|                 _tx_thread_system_suspend(thread_ptr); | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|                 /* Check that the event time stamp is unchanged.  A different | ||||
|                    timestamp means that a later event wrote over the byte | ||||
|                    allocate event.  In that case, do nothing here.  */ | ||||
|                 if (entry_ptr != TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     /* Is the timestamp the same?  */ | ||||
|                     if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) | ||||
|                     { | ||||
|  | ||||
|                         /* Timestamp is the same, update the entry with the address.  */ | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|                         entry_ptr -> tx_trace_buffer_entry_info_2 =  TX_POINTER_TO_ULONG_CONVERT(*memory_ptr); | ||||
| #else | ||||
|                        entry_ptr -> tx_trace_buffer_entry_information_field_2 =  TX_POINTER_TO_ULONG_CONVERT(*memory_ptr); | ||||
| #endif | ||||
|                     } | ||||
|                 } | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_LOGGING | ||||
|                 /* Check that the event time stamp is unchanged.  A different | ||||
|                    timestamp means that a later event wrote over the byte | ||||
|                    allocate event.  In that case, do nothing here.  */ | ||||
|                 if (lower_tbu ==  *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) && | ||||
|                     upper_tbu ==  *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET))) | ||||
|                 { | ||||
|  | ||||
|                     /* Store the address of the allocated fragment.  */ | ||||
|                     *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) =  (ULONG) *memory_ptr; | ||||
|                 } | ||||
| #endif | ||||
|  | ||||
|                 /* Return the completion status.  */ | ||||
|                 status =  thread_ptr -> tx_thread_suspend_status; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Immediate return, return error completion.  */ | ||||
|             status =  TX_NO_MEMORY; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										214
									
								
								Middlewares/ST/threadx/common/src/tx_byte_pool_cleanup.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								Middlewares/ST/threadx/common/src/tx_byte_pool_cleanup.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,214 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Byte Memory                                                         */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_byte_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_byte_pool_cleanup                               PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function processes byte allocate timeout and thread terminate  */ | ||||
| /*    actions that require the byte pool data structures to be cleaned    */ | ||||
| /*    up.                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                        Pointer to suspended thread's     */ | ||||
| /*                                        control block                   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_timeout                Thread timeout processing         */ | ||||
| /*    _tx_thread_terminate              Thread terminate processing       */ | ||||
| /*    _tx_thread_wait_abort             Thread wait abort processing      */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_byte_pool_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence) | ||||
| { | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
| #endif | ||||
|  | ||||
| TX_BYTE_POOL        *pool_ptr; | ||||
| UINT                suspended_count; | ||||
| TX_THREAD           *next_thread; | ||||
| TX_THREAD           *previous_thread; | ||||
|  | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|     /* Disable interrupts to remove the suspended thread from the byte pool.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Determine if the cleanup is still required.  */ | ||||
|     if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_byte_pool_cleanup)) | ||||
|     { | ||||
|  | ||||
|         /* Check for valid suspension sequence.  */ | ||||
|         if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence) | ||||
|         { | ||||
|  | ||||
|             /* Setup pointer to byte pool control block.  */ | ||||
|             pool_ptr =  TX_VOID_TO_BYTE_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); | ||||
|  | ||||
|             /* Check for a NULL byte pool pointer.  */ | ||||
|             if (pool_ptr != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Check for valid pool ID.  */ | ||||
|                 if (pool_ptr -> tx_byte_pool_id == TX_BYTE_POOL_ID) | ||||
|                 { | ||||
|  | ||||
|                     /* Determine if there are any thread suspensions.  */ | ||||
|                     if (pool_ptr -> tx_byte_pool_suspended_count != TX_NO_SUSPENSIONS) | ||||
|                     { | ||||
| #else | ||||
|  | ||||
|                         /* Setup pointer to byte pool control block.  */ | ||||
|                         pool_ptr =  TX_VOID_TO_BYTE_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); | ||||
| #endif | ||||
|  | ||||
|                         /* Thread suspended for memory... Clear the suspension cleanup flag.  */ | ||||
|                         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|                         /* Decrement the suspension count.  */ | ||||
|                         pool_ptr -> tx_byte_pool_suspended_count--; | ||||
|  | ||||
|                         /* Pickup the suspended count.  */ | ||||
|                         suspended_count =  pool_ptr -> tx_byte_pool_suspended_count; | ||||
|  | ||||
|                         /* Remove the suspended thread from the list.  */ | ||||
|  | ||||
|                         /* See if this is the only suspended thread on the list.  */ | ||||
|                         if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|                         { | ||||
|  | ||||
|                             /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|                             /* Update the head pointer.  */ | ||||
|                             pool_ptr -> tx_byte_pool_suspension_list =  TX_NULL; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* At least one more thread is on the same suspension list.  */ | ||||
|  | ||||
|                             /* Update the links of the adjacent threads.  */ | ||||
|                             next_thread =                                   thread_ptr -> tx_thread_suspended_next; | ||||
|                             previous_thread =                               thread_ptr -> tx_thread_suspended_previous; | ||||
|                             next_thread -> tx_thread_suspended_previous =   previous_thread; | ||||
|                             previous_thread -> tx_thread_suspended_next =   next_thread; | ||||
|  | ||||
|                             /* Determine if we need to update the head pointer.  */ | ||||
|                             if (pool_ptr -> tx_byte_pool_suspension_list == thread_ptr) | ||||
|                             { | ||||
|  | ||||
|                                 /* Update the list head pointer.  */ | ||||
|                                 pool_ptr -> tx_byte_pool_suspension_list =      next_thread; | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         /* Now we need to determine if this cleanup is from a terminate, timeout, | ||||
|                            or from a wait abort.  */ | ||||
|                         if (thread_ptr -> tx_thread_state == TX_BYTE_MEMORY) | ||||
|                         { | ||||
|  | ||||
|                             /* Timeout condition and the thread still suspended on the byte pool. | ||||
|                                Setup return error status and resume the thread.  */ | ||||
|  | ||||
| #ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                             /* Increment the total timeouts counter.  */ | ||||
|                             _tx_byte_pool_performance_timeout_count++; | ||||
|  | ||||
|                             /* Increment the number of timeouts on this byte pool.  */ | ||||
|                             pool_ptr -> tx_byte_pool_performance_timeout_count++; | ||||
| #endif | ||||
|  | ||||
|                             /* Setup return status.  */ | ||||
|                             thread_ptr -> tx_thread_suspend_status =  TX_NO_MEMORY; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                             /* Resume the thread!  */ | ||||
|                             _tx_thread_system_ni_resume(thread_ptr); | ||||
| #else | ||||
|  | ||||
|                             /* Temporarily disable preemption.  */ | ||||
|                             _tx_thread_preempt_disable++; | ||||
|  | ||||
|                             /* Restore interrupts.  */ | ||||
|                             TX_RESTORE | ||||
|  | ||||
|                             /* Resume the thread!  */ | ||||
|                             _tx_thread_system_resume(thread_ptr); | ||||
|  | ||||
|                             /* Disable interrupts.  */ | ||||
|                             TX_DISABLE | ||||
| #endif | ||||
|                         } | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										199
									
								
								Middlewares/ST/threadx/common/src/tx_byte_pool_create.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								Middlewares/ST/threadx/common/src/tx_byte_pool_create.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,199 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Byte Pool                                                           */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_byte_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_byte_pool_create                                PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function creates a pool of memory bytes in the specified       */ | ||||
| /*    memory area.                                                        */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                          Pointer to pool control block     */ | ||||
| /*    name_ptr                          Pointer to byte pool name         */ | ||||
| /*    pool_start                        Address of beginning of pool area */ | ||||
| /*    pool_size                         Number of bytes in the byte pool  */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, ULONG pool_size) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| UCHAR               *block_ptr; | ||||
| UCHAR               **block_indirect_ptr; | ||||
| UCHAR               *temp_ptr; | ||||
| TX_BYTE_POOL        *next_pool; | ||||
| TX_BYTE_POOL        *previous_pool; | ||||
| ALIGN_TYPE          *free_ptr; | ||||
|  | ||||
|  | ||||
|     /* Initialize the byte pool control block to all zeros.  */ | ||||
|     TX_MEMSET(pool_ptr, 0, (sizeof(TX_BYTE_POOL))); | ||||
|  | ||||
|     /* Round the pool size down to something that is evenly divisible by | ||||
|        an ULONG.  */ | ||||
|     pool_size =   (pool_size/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE)); | ||||
|  | ||||
|     /* Setup the basic byte pool fields.  */ | ||||
|     pool_ptr -> tx_byte_pool_name =              name_ptr; | ||||
|  | ||||
|     /* Save the start and size of the pool.  */ | ||||
|     pool_ptr -> tx_byte_pool_start =   TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); | ||||
|     pool_ptr -> tx_byte_pool_size =    pool_size; | ||||
|  | ||||
|     /* Setup memory list to the beginning as well as the search pointer.  */ | ||||
|     pool_ptr -> tx_byte_pool_list =    TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); | ||||
|     pool_ptr -> tx_byte_pool_search =  TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); | ||||
|  | ||||
|     /* Initially, the pool will have two blocks.  One large block at the | ||||
|        beginning that is available and a small allocated block at the end | ||||
|        of the pool that is there just for the algorithm.  Be sure to count | ||||
|        the available block's header in the available bytes count.  */ | ||||
|     pool_ptr -> tx_byte_pool_available =   pool_size - ((sizeof(VOID *)) + (sizeof(ALIGN_TYPE))); | ||||
|     pool_ptr -> tx_byte_pool_fragments =   ((UINT) 2); | ||||
|  | ||||
|     /* Each block contains a "next" pointer that points to the next block in the pool followed by a ALIGN_TYPE | ||||
|        field that contains either the constant TX_BYTE_BLOCK_FREE (if the block is free) or a pointer to the | ||||
|        owning pool (if the block is allocated).  */ | ||||
|  | ||||
|     /* Calculate the end of the pool's memory area.  */ | ||||
|     block_ptr =  TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); | ||||
|     block_ptr =  TX_UCHAR_POINTER_ADD(block_ptr, pool_size); | ||||
|  | ||||
|     /* Backup the end of the pool pointer and build the pre-allocated block.  */ | ||||
|     block_ptr =  TX_UCHAR_POINTER_SUB(block_ptr, (sizeof(ALIGN_TYPE))); | ||||
|  | ||||
|     /* Cast the pool pointer into a ULONG.  */ | ||||
|     temp_ptr =             TX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr); | ||||
|     block_indirect_ptr =   TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr); | ||||
|     *block_indirect_ptr =  temp_ptr; | ||||
|  | ||||
|     block_ptr =            TX_UCHAR_POINTER_SUB(block_ptr, (sizeof(UCHAR *))); | ||||
|     block_indirect_ptr =   TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr); | ||||
|     *block_indirect_ptr =  TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); | ||||
|  | ||||
|     /* Now setup the large available block in the pool.  */ | ||||
|     temp_ptr =             TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); | ||||
|     block_indirect_ptr =   TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(temp_ptr); | ||||
|     *block_indirect_ptr =  block_ptr; | ||||
|     block_ptr =            TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); | ||||
|     block_ptr =            TX_UCHAR_POINTER_ADD(block_ptr, (sizeof(UCHAR *))); | ||||
|     free_ptr =             TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(block_ptr); | ||||
|     *free_ptr =            TX_BYTE_BLOCK_FREE; | ||||
|  | ||||
|     /* Clear the owner id.  */ | ||||
|     pool_ptr -> tx_byte_pool_owner =  TX_NULL; | ||||
|  | ||||
|     /* Disable interrupts to place the byte pool on the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Setup the byte pool ID to make it valid.  */ | ||||
|     pool_ptr -> tx_byte_pool_id =  TX_BYTE_POOL_ID; | ||||
|  | ||||
|     /* Place the byte pool on the list of created byte pools.  First, | ||||
|        check for an empty list.  */ | ||||
|     if (_tx_byte_pool_created_count == TX_EMPTY) | ||||
|     { | ||||
|  | ||||
|         /* The created byte pool list is empty.  Add byte pool to empty list.  */ | ||||
|         _tx_byte_pool_created_ptr =                  pool_ptr; | ||||
|         pool_ptr -> tx_byte_pool_created_next =      pool_ptr; | ||||
|         pool_ptr -> tx_byte_pool_created_previous =  pool_ptr; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* This list is not NULL, add to the end of the list.  */ | ||||
|         next_pool =      _tx_byte_pool_created_ptr; | ||||
|         previous_pool =  next_pool -> tx_byte_pool_created_previous; | ||||
|  | ||||
|         /* Place the new byte pool in the list.  */ | ||||
|         next_pool -> tx_byte_pool_created_previous =  pool_ptr; | ||||
|         previous_pool -> tx_byte_pool_created_next =  pool_ptr; | ||||
|  | ||||
|         /* Setup this byte pool's created links.  */ | ||||
|         pool_ptr -> tx_byte_pool_created_previous =  previous_pool; | ||||
|         pool_ptr -> tx_byte_pool_created_next =      next_pool; | ||||
|     } | ||||
|  | ||||
|     /* Increment the number of created byte pools.  */ | ||||
|     _tx_byte_pool_created_count++; | ||||
|  | ||||
|     /* Optional byte pool create extended processing.  */ | ||||
|     TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr) | ||||
|  | ||||
|     /* If trace is enabled, register this object.  */ | ||||
|     TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_BYTE_POOL, pool_ptr, name_ptr, pool_size, 0) | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_CREATE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(pool_start), pool_size, TX_POINTER_TO_ULONG_CONVERT(&block_ptr), TX_TRACE_BYTE_POOL_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_BYTE_POOL_CREATE_INSERT | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										213
									
								
								Middlewares/ST/threadx/common/src/tx_byte_pool_delete.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								Middlewares/ST/threadx/common/src/tx_byte_pool_delete.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,213 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Byte Pool                                                           */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_byte_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_byte_pool_delete                                PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function deletes the specified byte pool.  All threads         */ | ||||
| /*    suspended on the byte pool are resumed with the TX_DELETED status   */ | ||||
| /*    code.                                                               */ | ||||
| /*                                                                        */ | ||||
| /*    It is important to note that the byte pool being deleted, or the    */ | ||||
| /*    memory associated with it should not be in use when this function   */ | ||||
| /*    is called.                                                          */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                          Pointer to pool control block     */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_byte_pool_delete(TX_BYTE_POOL *pool_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_THREAD       *next_thread; | ||||
| UINT            suspended_count; | ||||
| TX_BYTE_POOL    *next_pool; | ||||
| TX_BYTE_POOL    *previous_pool; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to remove the byte pool from the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_DELETE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_BYTE_POOL_EVENTS) | ||||
|  | ||||
|     /* Optional byte pool delete extended processing.  */ | ||||
|     TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr) | ||||
|  | ||||
|     /* If trace is enabled, unregister this object.  */ | ||||
|     TX_TRACE_OBJECT_UNREGISTER(pool_ptr) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_BYTE_POOL_DELETE_INSERT | ||||
|  | ||||
|     /* Clear the byte pool ID to make it invalid.  */ | ||||
|     pool_ptr -> tx_byte_pool_id =  TX_CLEAR_ID; | ||||
|  | ||||
|     /* Decrement the number of byte pools created.  */ | ||||
|     _tx_byte_pool_created_count--; | ||||
|  | ||||
|     /* See if the byte pool is the only one on the list.  */ | ||||
|     if (_tx_byte_pool_created_count == TX_EMPTY) | ||||
|     { | ||||
|  | ||||
|         /* Only created byte pool, just set the created list to NULL.  */ | ||||
|         _tx_byte_pool_created_ptr =  TX_NULL; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Link-up the neighbors.  */ | ||||
|         next_pool =                                   pool_ptr -> tx_byte_pool_created_next; | ||||
|         previous_pool =                               pool_ptr -> tx_byte_pool_created_previous; | ||||
|         next_pool -> tx_byte_pool_created_previous =  previous_pool; | ||||
|         previous_pool -> tx_byte_pool_created_next =  next_pool; | ||||
|  | ||||
|         /* See if we have to update the created list head pointer.  */ | ||||
|         if (_tx_byte_pool_created_ptr == pool_ptr) | ||||
|         { | ||||
|  | ||||
|             /* Yes, move the head pointer to the next link. */ | ||||
|             _tx_byte_pool_created_ptr =  next_pool; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Temporarily disable preemption.  */ | ||||
|     _tx_thread_preempt_disable++; | ||||
|  | ||||
|     /* Pickup the suspension information.  */ | ||||
|     thread_ptr =                                pool_ptr -> tx_byte_pool_suspension_list; | ||||
|     pool_ptr -> tx_byte_pool_suspension_list =  TX_NULL; | ||||
|     suspended_count =                           pool_ptr -> tx_byte_pool_suspended_count; | ||||
|     pool_ptr -> tx_byte_pool_suspended_count =  TX_NO_SUSPENSIONS; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Walk through the byte pool list to resume any and all threads suspended | ||||
|        on this byte pool.  */ | ||||
|     while (suspended_count != TX_NO_SUSPENSIONS) | ||||
|     { | ||||
|  | ||||
|         /* Decrement the suspension count.  */ | ||||
|         suspended_count--; | ||||
|  | ||||
|         /* Lockout interrupts.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* Clear the cleanup pointer, this prevents the timeout from doing | ||||
|            anything.  */ | ||||
|         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|         /* Set the return status in the thread to TX_DELETED.  */ | ||||
|         thread_ptr -> tx_thread_suspend_status =  TX_DELETED; | ||||
|  | ||||
|         /* Move the thread pointer ahead.  */ | ||||
|         next_thread =  thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Resume the thread!  */ | ||||
|         _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #else | ||||
|  | ||||
|         /* Temporarily disable preemption again.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Resume the thread.  */ | ||||
|         _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|         /* Move to next thread.  */ | ||||
|         thread_ptr =  next_thread; | ||||
|     } | ||||
|  | ||||
|     /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h.  */ | ||||
|     TX_BYTE_POOL_DELETE_PORT_COMPLETION(pool_ptr) | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Release previous preempt disable.  */ | ||||
|     _tx_thread_preempt_disable--; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Check for preemption.  */ | ||||
|     _tx_thread_system_preempt_check(); | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										148
									
								
								Middlewares/ST/threadx/common/src/tx_byte_pool_info_get.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								Middlewares/ST/threadx/common/src/tx_byte_pool_info_get.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Byte Memory                                                         */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_byte_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_byte_pool_info_get                              PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function retrieves information from the specified byte pool.   */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                          Pointer to byte pool control block*/ | ||||
| /*    name                              Destination for the pool name     */ | ||||
| /*    available_bytes                   Number of free bytes in byte pool */ | ||||
| /*    fragments                         Number of fragments in byte pool  */ | ||||
| /*    first_suspended                   Destination for pointer of first  */ | ||||
| /*                                        thread suspended on byte pool   */ | ||||
| /*    suspended_count                   Destination for suspended count   */ | ||||
| /*    next_pool                         Destination for pointer to next   */ | ||||
| /*                                        byte pool on the created list   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes, | ||||
|                     ULONG *fragments, TX_THREAD **first_suspended, | ||||
|                     ULONG *suspended_count, TX_BYTE_POOL **next_pool) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_INFO_GET, pool_ptr, 0, 0, 0, TX_TRACE_BYTE_POOL_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_BYTE_POOL_INFO_GET_INSERT | ||||
|  | ||||
|     /* Retrieve all the pertinent information and return it in the supplied | ||||
|        destinations.  */ | ||||
|  | ||||
|     /* Retrieve the name of the byte pool.  */ | ||||
|     if (name != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *name =  pool_ptr -> tx_byte_pool_name; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the number of available bytes in the byte pool.  */ | ||||
|     if (available_bytes != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *available_bytes =  pool_ptr -> tx_byte_pool_available; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the total number of bytes in the byte pool.  */ | ||||
|     if (fragments != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *fragments =  (ULONG) pool_ptr -> tx_byte_pool_fragments; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the first thread suspended on this byte pool.  */ | ||||
|     if (first_suspended != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *first_suspended =  pool_ptr -> tx_byte_pool_suspension_list; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the number of threads suspended on this byte pool.  */ | ||||
|     if (suspended_count != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *suspended_count =  (ULONG) pool_ptr -> tx_byte_pool_suspended_count; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the pointer to the next byte pool created.  */ | ||||
|     if (next_pool != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *next_pool =  pool_ptr -> tx_byte_pool_created_next; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										151
									
								
								Middlewares/ST/threadx/common/src/tx_byte_pool_initialize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								Middlewares/ST/threadx/common/src/tx_byte_pool_initialize.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,151 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Byte Pool                                                           */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_byte_pool.h" | ||||
|  | ||||
|  | ||||
| #ifndef TX_INLINE_INITIALIZATION | ||||
|  | ||||
| /* Locate byte pool component data in this file.  */ | ||||
|  | ||||
| /* Define the head pointer of the created byte pool list.  */ | ||||
|  | ||||
| TX_BYTE_POOL *   _tx_byte_pool_created_ptr; | ||||
|  | ||||
|  | ||||
| /* Define the variable that holds the number of created byte pools. */ | ||||
|  | ||||
| ULONG            _tx_byte_pool_created_count; | ||||
|  | ||||
|  | ||||
| #ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
| /* Define the total number of allocates.  */ | ||||
|  | ||||
| ULONG            _tx_byte_pool_performance_allocate_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of releases.  */ | ||||
|  | ||||
| ULONG            _tx_byte_pool_performance_release_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of adjacent memory fragment merges.  */ | ||||
|  | ||||
| ULONG            _tx_byte_pool_performance_merge_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of memory fragment splits.  */ | ||||
|  | ||||
| ULONG            _tx_byte_pool_performance_split_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of memory fragments searched during allocation.  */ | ||||
|  | ||||
| ULONG            _tx_byte_pool_performance_search_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of byte pool suspensions.  */ | ||||
|  | ||||
| ULONG            _tx_byte_pool_performance_suspension_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of byte pool timeouts.  */ | ||||
|  | ||||
| ULONG            _tx_byte_pool_performance_timeout_count; | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_byte_pool_initialize                            PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function initializes the various control data structures for   */ | ||||
| /*    the byte pool component.                                            */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_initialize_high_level         High level initialization         */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            opt out of function when    */ | ||||
| /*                                            TX_INLINE_INITIALIZATION is */ | ||||
| /*                                            defined,                    */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_byte_pool_initialize(VOID) | ||||
| { | ||||
|  | ||||
| #ifndef TX_DISABLE_REDUNDANT_CLEARING | ||||
|  | ||||
|     /* Initialize the head pointer of the created byte pools list and the | ||||
|        number of byte pools created.  */ | ||||
|     _tx_byte_pool_created_ptr =        TX_NULL; | ||||
|     _tx_byte_pool_created_count =      TX_EMPTY; | ||||
|  | ||||
| #ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Initialize byte pool performance counters.  */ | ||||
|     _tx_byte_pool_performance_allocate_count =    ((ULONG) 0); | ||||
|     _tx_byte_pool_performance_release_count =     ((ULONG) 0); | ||||
|     _tx_byte_pool_performance_merge_count =       ((ULONG) 0); | ||||
|     _tx_byte_pool_performance_split_count =       ((ULONG) 0); | ||||
|     _tx_byte_pool_performance_search_count =      ((ULONG) 0); | ||||
|     _tx_byte_pool_performance_suspension_count =  ((ULONG) 0); | ||||
|     _tx_byte_pool_performance_timeout_count =     ((ULONG) 0); | ||||
| #endif | ||||
| #endif | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										251
									
								
								Middlewares/ST/threadx/common/src/tx_byte_pool_prioritize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										251
									
								
								Middlewares/ST/threadx/common/src/tx_byte_pool_prioritize.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,251 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Byte Memory                                                         */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_byte_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_byte_pool_prioritize                           PORTABLE C       */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function places the highest priority suspended thread at the   */ | ||||
| /*    front of the suspension list.  All other threads remain in the same */ | ||||
| /*    FIFO suspension order.                                              */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                          Pointer to pool control block     */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_byte_pool_prioritize(TX_BYTE_POOL *pool_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_THREAD       *priority_thread_ptr; | ||||
| TX_THREAD       *head_ptr; | ||||
| UINT            suspended_count; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| UINT            list_changed; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_PRIORITIZE, pool_ptr, pool_ptr -> tx_byte_pool_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_BYTE_POOL_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_BYTE_POOL_PRIORITIZE_INSERT | ||||
|  | ||||
|     /* Pickup the suspended count.  */ | ||||
|     suspended_count =  pool_ptr -> tx_byte_pool_suspended_count; | ||||
|  | ||||
|     /* Determine if there are fewer than 2 suspended threads.  */ | ||||
|     if (suspended_count < ((UINT) 2)) | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|  | ||||
|     /* Determine if there how many threads are suspended on this byte memory pool.  */ | ||||
|     else if (suspended_count == ((UINT) 2)) | ||||
|     { | ||||
|  | ||||
|         /* Pickup the head pointer and the next pointer.  */ | ||||
|         head_ptr =  pool_ptr -> tx_byte_pool_suspension_list; | ||||
|         next_thread =  head_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|         /* Determine if the next suspended thread has a higher priority.  */ | ||||
|         if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority)) | ||||
|         { | ||||
|  | ||||
|             /* Yes, move the list head to the next thread.  */ | ||||
|             pool_ptr -> tx_byte_pool_suspension_list =  next_thread; | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Remember the suspension count and head pointer.  */ | ||||
|         head_ptr =   pool_ptr -> tx_byte_pool_suspension_list; | ||||
|  | ||||
|         /* Default the highest priority thread to the thread at the front of the list.  */ | ||||
|         priority_thread_ptr =  head_ptr; | ||||
|  | ||||
|         /* Setup search pointer.  */ | ||||
|         thread_ptr =  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|         /* Disable preemption.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Set the list changed flag to false.  */ | ||||
|         list_changed =  TX_FALSE; | ||||
|  | ||||
|         /* Search through the list to find the highest priority thread.  */ | ||||
|         do | ||||
|         { | ||||
|  | ||||
|             /* Is the current thread higher priority?  */ | ||||
|             if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, remember that this thread is the highest priority.  */ | ||||
|                 priority_thread_ptr =  thread_ptr; | ||||
|             } | ||||
|  | ||||
|             /* Restore interrupts temporarily.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Disable interrupts again.  */ | ||||
|             TX_DISABLE | ||||
|  | ||||
|             /* Determine if any changes to the list have occurred while | ||||
|                interrupts were enabled.  */ | ||||
|  | ||||
|             /* Is the list head the same?  */ | ||||
|             if (head_ptr != pool_ptr -> tx_byte_pool_suspension_list) | ||||
|             { | ||||
|  | ||||
|                 /* The list head has changed, set the list changed flag.  */ | ||||
|                 list_changed =  TX_TRUE; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Is the suspended count the same?  */ | ||||
|                 if (suspended_count != pool_ptr -> tx_byte_pool_suspended_count) | ||||
|                 { | ||||
|  | ||||
|                     /* The list head has changed, set the list changed flag.  */ | ||||
|                     list_changed =  TX_TRUE; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             /* Determine if the list has changed.  */ | ||||
|             if (list_changed == TX_FALSE) | ||||
|             { | ||||
|  | ||||
|                 /* Move the thread pointer to the next thread.  */ | ||||
|                 thread_ptr =  thread_ptr -> tx_thread_suspended_next; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Remember the suspension count and head pointer.  */ | ||||
|                 head_ptr =   pool_ptr -> tx_byte_pool_suspension_list; | ||||
|                 suspended_count =  pool_ptr -> tx_byte_pool_suspended_count; | ||||
|  | ||||
|                 /* Default the highest priority thread to the thread at the front of the list.  */ | ||||
|                 priority_thread_ptr =  head_ptr; | ||||
|  | ||||
|                 /* Setup search pointer.  */ | ||||
|                 thread_ptr =  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|                 /* Reset the list changed flag.  */ | ||||
|                 list_changed =  TX_FALSE; | ||||
|             } | ||||
|  | ||||
|         } while (thread_ptr != head_ptr); | ||||
|  | ||||
|         /* Release preemption.  */ | ||||
|         _tx_thread_preempt_disable--; | ||||
|  | ||||
|         /* Now determine if the highest priority thread is at the front | ||||
|            of the list.  */ | ||||
|         if (priority_thread_ptr != head_ptr) | ||||
|         { | ||||
|  | ||||
|             /* No, we need to move the highest priority suspended thread to the | ||||
|                front of the list.  */ | ||||
|  | ||||
|             /* First, remove the highest priority thread by updating the | ||||
|                adjacent suspended threads.  */ | ||||
|             next_thread =                                  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|             previous_thread =                              priority_thread_ptr -> tx_thread_suspended_previous; | ||||
|             next_thread -> tx_thread_suspended_previous =  previous_thread; | ||||
|             previous_thread -> tx_thread_suspended_next =  next_thread; | ||||
|  | ||||
|             /* Now, link the highest priority thread at the front of the list.  */ | ||||
|             previous_thread =                                      head_ptr -> tx_thread_suspended_previous; | ||||
|             priority_thread_ptr -> tx_thread_suspended_next =      head_ptr; | ||||
|             priority_thread_ptr -> tx_thread_suspended_previous =  previous_thread; | ||||
|             previous_thread -> tx_thread_suspended_next =          priority_thread_ptr; | ||||
|             head_ptr -> tx_thread_suspended_previous =             priority_thread_ptr; | ||||
|  | ||||
|             /* Move the list head pointer to the highest priority suspended thread.  */ | ||||
|             pool_ptr -> tx_byte_pool_suspension_list =  priority_thread_ptr; | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Check for preemption.  */ | ||||
|         _tx_thread_system_preempt_check(); | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										354
									
								
								Middlewares/ST/threadx/common/src/tx_byte_pool_search.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										354
									
								
								Middlewares/ST/threadx/common/src/tx_byte_pool_search.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,354 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Byte Pool                                                           */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_byte_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_byte_pool_search                                PORTABLE C      */ | ||||
| /*                                                           6.1.7        */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function searches a byte pool for a memory block to satisfy    */ | ||||
| /*    the requested number of bytes.  Merging of adjacent free blocks     */ | ||||
| /*    takes place during the search and a split of the block that         */ | ||||
| /*    satisfies the request may occur before this function returns.       */ | ||||
| /*                                                                        */ | ||||
| /*    It is assumed that this function is called with interrupts enabled  */ | ||||
| /*    and with the tx_pool_owner field set to the thread performing the   */ | ||||
| /*    search.  Also note that the search can occur during allocation and  */ | ||||
| /*    release of a memory block.                                          */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                          Pointer to pool control block     */ | ||||
| /*    memory_size                       Number of bytes required          */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    UCHAR *                           Pointer to the allocated memory,  */ | ||||
| /*                                        if successful.  Otherwise, a    */ | ||||
| /*                                        NULL is returned                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_byte_allocate                 Allocate bytes of memory          */ | ||||
| /*    _tx_byte_release                  Release bytes of memory           */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020      William E. Lamie        Initial Version 6.0           */ | ||||
| /*  09-30-2020      Yuxin Zhou              Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*  06-02-2021      Scott Larson            Improve possible free bytes   */ | ||||
| /*                                            calculation,                */ | ||||
| /*                                            resulting in version 6.1.7  */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UCHAR  *_tx_byte_pool_search(TX_BYTE_POOL *pool_ptr, ULONG memory_size) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| UCHAR           *current_ptr; | ||||
| UCHAR           *next_ptr; | ||||
| UCHAR           **this_block_link_ptr; | ||||
| UCHAR           **next_block_link_ptr; | ||||
| ULONG           available_bytes; | ||||
| UINT            examine_blocks; | ||||
| UINT            first_free_block_found =  TX_FALSE; | ||||
| TX_THREAD       *thread_ptr; | ||||
| ALIGN_TYPE      *free_ptr; | ||||
| UCHAR           *work_ptr; | ||||
| ULONG           total_theoretical_available; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* First, determine if there are enough bytes in the pool.  */ | ||||
|     /* Theoretical bytes available = free bytes + ((fragments-2) * overhead of each block) */ | ||||
|     total_theoretical_available = pool_ptr -> tx_byte_pool_available + ((pool_ptr -> tx_byte_pool_fragments - 2) * ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE)))); | ||||
|     if (memory_size >= total_theoretical_available) | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Not enough memory, return a NULL pointer.  */ | ||||
|         current_ptr =  TX_NULL; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Pickup thread pointer.  */ | ||||
|         TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
|         /* Setup ownership of the byte pool.  */ | ||||
|         pool_ptr -> tx_byte_pool_owner =  thread_ptr; | ||||
|  | ||||
|         /* Walk through the memory pool in search for a large enough block.  */ | ||||
|         current_ptr =      pool_ptr -> tx_byte_pool_search; | ||||
|         examine_blocks =   pool_ptr -> tx_byte_pool_fragments + ((UINT) 1); | ||||
|         available_bytes =  ((ULONG) 0); | ||||
|         do | ||||
|         { | ||||
|  | ||||
|  | ||||
| #ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|             /* Increment the total fragment search counter.  */ | ||||
|             _tx_byte_pool_performance_search_count++; | ||||
|  | ||||
|             /* Increment the number of fragments searched on this pool.  */ | ||||
|             pool_ptr -> tx_byte_pool_performance_search_count++; | ||||
| #endif | ||||
|  | ||||
|             /* Check to see if this block is free.  */ | ||||
|             work_ptr =  TX_UCHAR_POINTER_ADD(current_ptr, (sizeof(UCHAR *))); | ||||
|             free_ptr =  TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(work_ptr); | ||||
|             if ((*free_ptr) == TX_BYTE_BLOCK_FREE) | ||||
|             { | ||||
|  | ||||
|                 /* Determine if this is the first free block.  */ | ||||
|                 if (first_free_block_found == TX_FALSE) | ||||
|                 { | ||||
|                     /* This is the first free block.  */ | ||||
|                     pool_ptr->tx_byte_pool_search =  current_ptr; | ||||
|  | ||||
|                     /* Set the flag to indicate we have found the first free | ||||
|                        block.  */ | ||||
|                     first_free_block_found =  TX_TRUE; | ||||
|                 } | ||||
|  | ||||
|                 /* Block is free, see if it is large enough.  */ | ||||
|  | ||||
|                 /* Pickup the next block's pointer.  */ | ||||
|                 this_block_link_ptr =  TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr); | ||||
|                 next_ptr =             *this_block_link_ptr; | ||||
|  | ||||
|                 /* Calculate the number of bytes available in this block.  */ | ||||
|                 available_bytes =   TX_UCHAR_POINTER_DIF(next_ptr, current_ptr); | ||||
|                 available_bytes =   available_bytes - ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE))); | ||||
|  | ||||
|                 /* If this is large enough, we are done because our first-fit algorithm | ||||
|                    has been satisfied!  */ | ||||
|                 if (available_bytes >= memory_size) | ||||
|                 { | ||||
|                     /* Get out of the search loop!  */ | ||||
|                     break; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* Clear the available bytes variable.  */ | ||||
|                     available_bytes =  ((ULONG) 0); | ||||
|  | ||||
|                     /* Not enough memory, check to see if the neighbor is | ||||
|                        free and can be merged.  */ | ||||
|                     work_ptr =  TX_UCHAR_POINTER_ADD(next_ptr, (sizeof(UCHAR *))); | ||||
|                     free_ptr =  TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(work_ptr); | ||||
|                     if ((*free_ptr) == TX_BYTE_BLOCK_FREE) | ||||
|                     { | ||||
|  | ||||
|                         /* Yes, neighbor block can be merged!  This is quickly accomplished | ||||
|                            by updating the current block with the next blocks pointer.  */ | ||||
|                         next_block_link_ptr =  TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(next_ptr); | ||||
|                         *this_block_link_ptr =  *next_block_link_ptr; | ||||
|  | ||||
|                         /* Reduce the fragment total.  We don't need to increase the bytes | ||||
|                            available because all free headers are also included in the available | ||||
|                            count.  */ | ||||
|                         pool_ptr -> tx_byte_pool_fragments--; | ||||
|  | ||||
| #ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                         /* Increment the total merge counter.  */ | ||||
|                         _tx_byte_pool_performance_merge_count++; | ||||
|  | ||||
|                         /* Increment the number of blocks merged on this pool.  */ | ||||
|                         pool_ptr -> tx_byte_pool_performance_merge_count++; | ||||
| #endif | ||||
|  | ||||
|                         /* See if the search pointer is affected.  */ | ||||
|                         if (pool_ptr -> tx_byte_pool_search ==  next_ptr) | ||||
|                         { | ||||
|                             /* Yes, update the search pointer.   */ | ||||
|                             pool_ptr -> tx_byte_pool_search =  current_ptr; | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         /* Neighbor is not free so we can skip over it!  */ | ||||
|                         next_block_link_ptr =  TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(next_ptr); | ||||
|                         current_ptr =  *next_block_link_ptr; | ||||
|  | ||||
|                         /* Decrement the examined block count to account for this one.  */ | ||||
|                         if (examine_blocks != ((UINT) 0)) | ||||
|                         { | ||||
|                             examine_blocks--; | ||||
|  | ||||
| #ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                             /* Increment the total fragment search counter.  */ | ||||
|                             _tx_byte_pool_performance_search_count++; | ||||
|  | ||||
|                             /* Increment the number of fragments searched on this pool.  */ | ||||
|                             pool_ptr -> tx_byte_pool_performance_search_count++; | ||||
| #endif | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Block is not free, move to next block.  */ | ||||
|                 this_block_link_ptr =  TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr); | ||||
|                 current_ptr =  *this_block_link_ptr; | ||||
|             } | ||||
|  | ||||
|             /* Another block has been searched... decrement counter.  */ | ||||
|             if (examine_blocks != ((UINT) 0)) | ||||
|             { | ||||
|  | ||||
|                 examine_blocks--; | ||||
|             } | ||||
|  | ||||
|             /* Restore interrupts temporarily.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Disable interrupts.  */ | ||||
|             TX_DISABLE | ||||
|  | ||||
|             /* Determine if anything has changed in terms of pool ownership.  */ | ||||
|             if (pool_ptr -> tx_byte_pool_owner != thread_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Pool changed ownership in the brief period interrupts were | ||||
|                    enabled.  Reset the search.  */ | ||||
|                 current_ptr =      pool_ptr -> tx_byte_pool_search; | ||||
|                 examine_blocks =   pool_ptr -> tx_byte_pool_fragments + ((UINT) 1); | ||||
|  | ||||
|                 /* Setup our ownership again.  */ | ||||
|                 pool_ptr -> tx_byte_pool_owner =  thread_ptr; | ||||
|             } | ||||
|         } while(examine_blocks != ((UINT) 0)); | ||||
|  | ||||
|         /* Determine if a block was found.  If so, determine if it needs to be | ||||
|            split.  */ | ||||
|         if (available_bytes != ((ULONG) 0)) | ||||
|         { | ||||
|  | ||||
|             /* Determine if we need to split this block.  */ | ||||
|             if ((available_bytes - memory_size) >= ((ULONG) TX_BYTE_BLOCK_MIN)) | ||||
|             { | ||||
|  | ||||
|                 /* Split the block.  */ | ||||
|                 next_ptr =  TX_UCHAR_POINTER_ADD(current_ptr, (memory_size + ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE))))); | ||||
|  | ||||
|                 /* Setup the new free block.  */ | ||||
|                 next_block_link_ptr =   TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(next_ptr); | ||||
|                 this_block_link_ptr =   TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr); | ||||
|                 *next_block_link_ptr =  *this_block_link_ptr; | ||||
|                 work_ptr =              TX_UCHAR_POINTER_ADD(next_ptr, (sizeof(UCHAR *))); | ||||
|                 free_ptr =              TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(work_ptr); | ||||
|                 *free_ptr =             TX_BYTE_BLOCK_FREE; | ||||
|  | ||||
|                 /* Increase the total fragment counter.  */ | ||||
|                 pool_ptr -> tx_byte_pool_fragments++; | ||||
|  | ||||
|                 /* Update the current pointer to point at the newly created block.  */ | ||||
|                 *this_block_link_ptr =  next_ptr; | ||||
|  | ||||
|                 /* Set available equal to memory size for subsequent calculation.  */ | ||||
|                 available_bytes =  memory_size; | ||||
|  | ||||
| #ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                 /* Increment the total split counter.  */ | ||||
|                 _tx_byte_pool_performance_split_count++; | ||||
|  | ||||
|                 /* Increment the number of blocks split on this pool.  */ | ||||
|                 pool_ptr -> tx_byte_pool_performance_split_count++; | ||||
| #endif | ||||
|             } | ||||
|  | ||||
|             /* In any case, mark the current block as allocated.  */ | ||||
|             work_ptr =              TX_UCHAR_POINTER_ADD(current_ptr, (sizeof(UCHAR *))); | ||||
|             this_block_link_ptr =   TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr); | ||||
|             *this_block_link_ptr =  TX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr); | ||||
|  | ||||
|             /* Reduce the number of available bytes in the pool.  */ | ||||
|             pool_ptr -> tx_byte_pool_available =  (pool_ptr -> tx_byte_pool_available - available_bytes) - ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE))); | ||||
|  | ||||
|             /* Determine if the search pointer needs to be updated. This is only done | ||||
|                if the search pointer matches the block to be returned.  */ | ||||
|             if (current_ptr == pool_ptr -> tx_byte_pool_search) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, update the search pointer to the next block.  */ | ||||
|                 this_block_link_ptr =   TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr); | ||||
|                 pool_ptr -> tx_byte_pool_search =  *this_block_link_ptr; | ||||
|             } | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Adjust the pointer for the application.  */ | ||||
|             current_ptr =  TX_UCHAR_POINTER_ADD(current_ptr, (((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE))))); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Set current pointer to NULL to indicate nothing was found.  */ | ||||
|             current_ptr =  TX_NULL; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Return the search pointer.  */ | ||||
|     return(current_ptr); | ||||
| } | ||||
|  | ||||
							
								
								
									
										378
									
								
								Middlewares/ST/threadx/common/src/tx_byte_release.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										378
									
								
								Middlewares/ST/threadx/common/src/tx_byte_release.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,378 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Byte Memory                                                         */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_byte_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_byte_release                                    PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function returns previously allocated memory to its            */ | ||||
| /*    associated memory byte pool.                                        */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    memory_ptr                        Pointer to allocated memory       */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    [TX_PTR_ERROR | TX_SUCCESS]       Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*    _tx_byte_pool_search              Search the byte pool for memory   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_byte_release(VOID *memory_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| UINT                status; | ||||
| TX_BYTE_POOL        *pool_ptr; | ||||
| TX_THREAD           *thread_ptr; | ||||
| UCHAR               *work_ptr; | ||||
| UCHAR               *temp_ptr; | ||||
| UCHAR               *next_block_ptr; | ||||
| TX_THREAD           *susp_thread_ptr; | ||||
| UINT                suspended_count; | ||||
| TX_THREAD           *next_thread; | ||||
| TX_THREAD           *previous_thread; | ||||
| ULONG               memory_size; | ||||
| ALIGN_TYPE          *free_ptr; | ||||
| TX_BYTE_POOL        **byte_pool_ptr; | ||||
| UCHAR               **block_link_ptr; | ||||
| UCHAR               **suspend_info_ptr; | ||||
|  | ||||
|  | ||||
|     /* Default to successful status.  */ | ||||
|     status =  TX_SUCCESS; | ||||
|  | ||||
|     /* Set the pool pointer to NULL.  */ | ||||
|     pool_ptr =  TX_NULL; | ||||
|  | ||||
|     /* Lockout interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Determine if the memory pointer is valid.  */ | ||||
|     work_ptr =  TX_VOID_TO_UCHAR_POINTER_CONVERT(memory_ptr); | ||||
|     if (work_ptr != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Back off the memory pointer to pickup its header.  */ | ||||
|         work_ptr =  TX_UCHAR_POINTER_SUB(work_ptr, ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE)))); | ||||
|  | ||||
|         /* There is a pointer, pickup the pool pointer address.  */ | ||||
|         temp_ptr =  TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *))); | ||||
|         free_ptr =  TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(temp_ptr); | ||||
|         if ((*free_ptr) != TX_BYTE_BLOCK_FREE) | ||||
|         { | ||||
|  | ||||
|             /* Pickup the pool pointer.  */ | ||||
|             temp_ptr =  TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *))); | ||||
|             byte_pool_ptr =  TX_UCHAR_TO_INDIRECT_BYTE_POOL_POINTER(temp_ptr); | ||||
|             pool_ptr =  *byte_pool_ptr; | ||||
|  | ||||
|             /* See if we have a valid pool pointer.  */ | ||||
|             if (pool_ptr == TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Return pointer error.  */ | ||||
|                 status =  TX_PTR_ERROR; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* See if we have a valid pool.  */ | ||||
|                 if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID) | ||||
|                 { | ||||
|  | ||||
|                     /* Return pointer error.  */ | ||||
|                     status =  TX_PTR_ERROR; | ||||
|  | ||||
|                     /* Reset the pool pointer is NULL.  */ | ||||
|                     pool_ptr =  TX_NULL; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Return pointer error.  */ | ||||
|             status =  TX_PTR_ERROR; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Return pointer error.  */ | ||||
|         status =  TX_PTR_ERROR; | ||||
|     } | ||||
|  | ||||
|     /* Determine if the pointer is valid.  */ | ||||
|     if (pool_ptr == TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* At this point, we know that the pointer is valid.  */ | ||||
|  | ||||
|         /* Pickup thread pointer.  */ | ||||
|         TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
|         /* Indicate that this thread is the current owner.  */ | ||||
|         pool_ptr -> tx_byte_pool_owner =  thread_ptr; | ||||
|  | ||||
| #ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|         /* Increment the total release counter.  */ | ||||
|         _tx_byte_pool_performance_release_count++; | ||||
|  | ||||
|         /* Increment the number of releases on this pool.  */ | ||||
|         pool_ptr -> tx_byte_pool_performance_release_count++; | ||||
| #endif | ||||
|  | ||||
|         /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|         TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_RELEASE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(memory_ptr), pool_ptr -> tx_byte_pool_suspended_count, pool_ptr -> tx_byte_pool_available, TX_TRACE_BYTE_POOL_EVENTS) | ||||
|  | ||||
|         /* Log this kernel call.  */ | ||||
|         TX_EL_BYTE_RELEASE_INSERT | ||||
|  | ||||
|         /* Release the memory.  */ | ||||
|         temp_ptr =   TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *))); | ||||
|         free_ptr =   TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(temp_ptr); | ||||
|         *free_ptr =  TX_BYTE_BLOCK_FREE; | ||||
|  | ||||
|         /* Update the number of available bytes in the pool.  */ | ||||
|         block_link_ptr =  TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr); | ||||
|         next_block_ptr =  *block_link_ptr; | ||||
|         pool_ptr -> tx_byte_pool_available = | ||||
|             pool_ptr -> tx_byte_pool_available + TX_UCHAR_POINTER_DIF(next_block_ptr, work_ptr); | ||||
|  | ||||
|         /* Determine if the free block is prior to current search pointer.  */ | ||||
|         if (work_ptr < (pool_ptr -> tx_byte_pool_search)) | ||||
|         { | ||||
|  | ||||
|             /* Yes, update the search pointer to the released block.  */ | ||||
|             pool_ptr -> tx_byte_pool_search =  work_ptr; | ||||
|         } | ||||
|  | ||||
|         /* Determine if there are threads suspended on this byte pool.  */ | ||||
|         if (pool_ptr -> tx_byte_pool_suspended_count != TX_NO_SUSPENSIONS) | ||||
|         { | ||||
|  | ||||
|             /* Now examine the suspension list to find threads waiting for | ||||
|                memory.  Maybe it is now available!  */ | ||||
|             while (pool_ptr -> tx_byte_pool_suspended_count != TX_NO_SUSPENSIONS) | ||||
|             { | ||||
|  | ||||
|                 /* Pickup the first suspended thread pointer.  */ | ||||
|                 susp_thread_ptr =  pool_ptr -> tx_byte_pool_suspension_list; | ||||
|  | ||||
|                 /* Pickup the size of the memory the thread is requesting.  */ | ||||
|                 memory_size =  susp_thread_ptr -> tx_thread_suspend_info; | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* See if the request can be satisfied.  */ | ||||
|                 work_ptr =  _tx_byte_pool_search(pool_ptr, memory_size); | ||||
|  | ||||
|                 /* Optional processing extension.  */ | ||||
|                 TX_BYTE_RELEASE_EXTENSION | ||||
|  | ||||
|                 /* Disable interrupts.  */ | ||||
|                 TX_DISABLE | ||||
|  | ||||
|                 /* Indicate that this thread is the current owner.  */ | ||||
|                 pool_ptr -> tx_byte_pool_owner =  thread_ptr; | ||||
|  | ||||
|                 /* If there is not enough memory, break this loop!  */ | ||||
|                 if (work_ptr == TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                   /* Break out of the loop.  */ | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 /* Check to make sure the thread is still suspended.  */ | ||||
|                 if (susp_thread_ptr ==  pool_ptr -> tx_byte_pool_suspension_list) | ||||
|                 { | ||||
|  | ||||
|                     /* Also, makes sure the memory size is the same.  */ | ||||
|                     if (susp_thread_ptr -> tx_thread_suspend_info == memory_size) | ||||
|                     { | ||||
|  | ||||
|                         /* Remove the suspended thread from the list.  */ | ||||
|  | ||||
|                         /* Decrement the number of threads suspended.  */ | ||||
|                         pool_ptr -> tx_byte_pool_suspended_count--; | ||||
|  | ||||
|                         /* Pickup the suspended count.  */ | ||||
|                         suspended_count =  pool_ptr -> tx_byte_pool_suspended_count; | ||||
|  | ||||
|                         /* See if this is the only suspended thread on the list.  */ | ||||
|                         if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|                         { | ||||
|  | ||||
|                             /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|                             /* Update the head pointer.  */ | ||||
|                             pool_ptr -> tx_byte_pool_suspension_list =  TX_NULL; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* At least one more thread is on the same expiration list.  */ | ||||
|  | ||||
|                             /* Update the list head pointer.  */ | ||||
|                             next_thread =                                susp_thread_ptr -> tx_thread_suspended_next; | ||||
|                             pool_ptr -> tx_byte_pool_suspension_list =   next_thread; | ||||
|  | ||||
|                             /* Update the links of the adjacent threads.  */ | ||||
|                             previous_thread =                              susp_thread_ptr -> tx_thread_suspended_previous; | ||||
|                             next_thread -> tx_thread_suspended_previous =  previous_thread; | ||||
|                             previous_thread -> tx_thread_suspended_next =  next_thread; | ||||
|                         } | ||||
|  | ||||
|                         /* Prepare for resumption of the thread.  */ | ||||
|  | ||||
|                         /* Clear cleanup routine to avoid timeout.  */ | ||||
|                         susp_thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|                         /* Return this block pointer to the suspended thread waiting for | ||||
|                            a block.  */ | ||||
|                         suspend_info_ptr =   TX_VOID_TO_INDIRECT_UCHAR_POINTER_CONVERT(susp_thread_ptr -> tx_thread_additional_suspend_info); | ||||
|                         *suspend_info_ptr =  work_ptr; | ||||
|  | ||||
|                         /* Clear the memory pointer to indicate that it was given to the suspended thread.  */ | ||||
|                         work_ptr =  TX_NULL; | ||||
|  | ||||
|                         /* Put return status into the thread control block.  */ | ||||
|                         susp_thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                         /* Resume the thread!  */ | ||||
|                         _tx_thread_system_ni_resume(susp_thread_ptr); | ||||
|  | ||||
|                         /* Restore interrupts.  */ | ||||
|                         TX_RESTORE | ||||
| #else | ||||
|                         /* Temporarily disable preemption.  */ | ||||
|                         _tx_thread_preempt_disable++; | ||||
|  | ||||
|                         /* Restore interrupts.  */ | ||||
|                         TX_RESTORE | ||||
|  | ||||
|                         /* Resume thread.  */ | ||||
|                         _tx_thread_system_resume(susp_thread_ptr); | ||||
| #endif | ||||
|  | ||||
|                         /* Lockout interrupts.  */ | ||||
|                         TX_DISABLE | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 /* Determine if the memory was given to the suspended thread.  */ | ||||
|                 if (work_ptr != TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     /* No, it wasn't given to the suspended thread.  */ | ||||
|  | ||||
|                     /* Put the memory back on the available list since this thread is no longer | ||||
|                        suspended.  */ | ||||
|                     work_ptr =  TX_UCHAR_POINTER_SUB(work_ptr, (((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE))))); | ||||
|                     temp_ptr =  TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *))); | ||||
|                     free_ptr =  TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(temp_ptr); | ||||
|                     *free_ptr =  TX_BYTE_BLOCK_FREE; | ||||
|  | ||||
|                     /* Update the number of available bytes in the pool.  */ | ||||
|                     block_link_ptr =  TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr); | ||||
|                     next_block_ptr =  *block_link_ptr; | ||||
|                     pool_ptr -> tx_byte_pool_available = | ||||
|                         pool_ptr -> tx_byte_pool_available + TX_UCHAR_POINTER_DIF(next_block_ptr, work_ptr); | ||||
|  | ||||
|                     /* Determine if the current pointer is before the search pointer.  */ | ||||
|                     if (work_ptr < (pool_ptr -> tx_byte_pool_search)) | ||||
|                     { | ||||
|  | ||||
|                         /* Yes, update the search pointer.  */ | ||||
|                         pool_ptr -> tx_byte_pool_search =  work_ptr; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Check for preemption.  */ | ||||
|             _tx_thread_system_preempt_check(); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* No, threads suspended, restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										239
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_cleanup.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_cleanup.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,239 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Event Flags                                                         */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_event_flags.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_event_flags_cleanup                             PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function processes event flags timeout and thread terminate    */ | ||||
| /*    actions that require the event flags data structures to be cleaned  */ | ||||
| /*    up.                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                        Pointer to suspended thread's     */ | ||||
| /*                                        control block                   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_timeout                Thread timeout processing         */ | ||||
| /*    _tx_thread_terminate              Thread terminate processing       */ | ||||
| /*    _tx_thread_wait_abort             Thread wait abort processing      */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_event_flags_cleanup(TX_THREAD  *thread_ptr, ULONG suspension_sequence) | ||||
| { | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
| #endif | ||||
|  | ||||
| TX_EVENT_FLAGS_GROUP        *group_ptr; | ||||
| UINT                        suspended_count; | ||||
| TX_THREAD                   *suspension_head; | ||||
| TX_THREAD                   *next_thread; | ||||
| TX_THREAD                   *previous_thread; | ||||
|  | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|     /* Disable interrupts to remove the suspended thread from the event flags group.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Determine if the cleanup is still required.  */ | ||||
|     if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_event_flags_cleanup)) | ||||
|     { | ||||
|  | ||||
|         /* Check for valid suspension sequence.  */ | ||||
|         if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence) | ||||
|         { | ||||
|  | ||||
|             /* Setup pointer to event flags control block.  */ | ||||
|             group_ptr =  TX_VOID_TO_EVENT_FLAGS_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); | ||||
|  | ||||
|             /* Check for a NULL event flags control block pointer.  */ | ||||
|             if (group_ptr != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Is the group pointer ID valid?  */ | ||||
|                 if (group_ptr -> tx_event_flags_group_id == TX_EVENT_FLAGS_ID) | ||||
|                 { | ||||
|  | ||||
|                     /* Determine if there are any thread suspensions.  */ | ||||
|                     if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS) | ||||
|                     { | ||||
| #else | ||||
|  | ||||
|                         /* Setup pointer to event flags control block.  */ | ||||
|                         group_ptr =  TX_VOID_TO_EVENT_FLAGS_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); | ||||
| #endif | ||||
|  | ||||
|                         /* Yes, we still have thread suspension!  */ | ||||
|  | ||||
|                         /* Clear the suspension cleanup flag.  */ | ||||
|                         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|                         /* Pickup the suspended count.  */ | ||||
|                         suspended_count =  group_ptr -> tx_event_flags_group_suspended_count; | ||||
|  | ||||
|                         /* Pickup the suspension head.  */ | ||||
|                         suspension_head =  group_ptr -> tx_event_flags_group_suspension_list; | ||||
|  | ||||
|                         /* Determine if the cleanup is being done while a set operation was interrupted.  If the | ||||
|                            suspended count is non-zero and the suspension head is NULL, the list is being processed | ||||
|                            and cannot be touched from here. The suspension list removal will instead take place | ||||
|                            inside the event flag set code.  */ | ||||
|                         if (suspension_head != TX_NULL) | ||||
|                         { | ||||
|  | ||||
|                             /* Remove the suspended thread from the list.  */ | ||||
|  | ||||
|                             /* Decrement the local suspension count.  */ | ||||
|                             suspended_count--; | ||||
|  | ||||
|                             /* Store the updated suspended count.  */ | ||||
|                             group_ptr -> tx_event_flags_group_suspended_count =  suspended_count; | ||||
|  | ||||
|                             /* See if this is the only suspended thread on the list.  */ | ||||
|                             if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|                             { | ||||
|  | ||||
|                                 /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|                                 /* Update the head pointer.  */ | ||||
|                                 group_ptr -> tx_event_flags_group_suspension_list =  TX_NULL; | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|  | ||||
|                                 /* At least one more thread is on the same suspension list.  */ | ||||
|  | ||||
|                                 /* Update the links of the adjacent threads.  */ | ||||
|                                 next_thread =                                  thread_ptr -> tx_thread_suspended_next; | ||||
|                                 previous_thread =                              thread_ptr -> tx_thread_suspended_previous; | ||||
|                                 next_thread -> tx_thread_suspended_previous =  previous_thread; | ||||
|                                 previous_thread -> tx_thread_suspended_next =  next_thread; | ||||
|  | ||||
|                                 /* Determine if we need to update the head pointer.  */ | ||||
|                                 if (suspension_head == thread_ptr) | ||||
|                                 { | ||||
|  | ||||
|                                     /* Update the list head pointer.  */ | ||||
|                                     group_ptr -> tx_event_flags_group_suspension_list =  next_thread; | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* In this case, the search pointer in an interrupted event flag set must be reset.  */ | ||||
|                             group_ptr -> tx_event_flags_group_reset_search =  TX_TRUE; | ||||
|                         } | ||||
|  | ||||
|                         /* Now we need to determine if this cleanup is from a terminate, timeout, | ||||
|                            or from a wait abort.  */ | ||||
|                         if (thread_ptr -> tx_thread_state == TX_EVENT_FLAG) | ||||
|                         { | ||||
|  | ||||
|                             /* Timeout condition and the thread still suspended on the event flags group. | ||||
|                                Setup return error status and resume the thread.  */ | ||||
|  | ||||
| #ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                             /* Increment the total timeouts counter.  */ | ||||
|                             _tx_event_flags_performance_timeout_count++; | ||||
|  | ||||
|                             /* Increment the number of timeouts on this event flags group.  */ | ||||
|                             group_ptr -> tx_event_flags_group____performance_timeout_count++; | ||||
| #endif | ||||
|  | ||||
|                             /* Setup return status.  */ | ||||
|                             thread_ptr -> tx_thread_suspend_status =  TX_NO_EVENTS; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                             /* Resume the thread!  */ | ||||
|                             _tx_thread_system_ni_resume(thread_ptr); | ||||
| #else | ||||
|  | ||||
|                            /* Temporarily disable preemption.  */ | ||||
|                             _tx_thread_preempt_disable++; | ||||
|  | ||||
|                             /* Restore interrupts.  */ | ||||
|                             TX_RESTORE | ||||
|  | ||||
|                             /* Resume the thread!  Check for preemption even though we are executing | ||||
|                                from the system timer thread right now which normally executes at the | ||||
|                                highest priority.  */ | ||||
|                             _tx_thread_system_resume(thread_ptr); | ||||
|  | ||||
|                             /* Disable interrupts.  */ | ||||
|                             TX_DISABLE | ||||
| #endif | ||||
|                         } | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										143
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_create.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_create.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Event Flags                                                         */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_event_flags.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_event_flags_create                              PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function creates a group of 32 event flags.  All the flags are */ | ||||
| /*    initially in a cleared state.                                       */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    group_ptr                         Pointer to event flags group      */ | ||||
| /*                                        control block                   */ | ||||
| /*    name_ptr                          Pointer to event flags name       */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_EVENT_FLAGS_GROUP    *next_group; | ||||
| TX_EVENT_FLAGS_GROUP    *previous_group; | ||||
|  | ||||
|  | ||||
|     /* Initialize event flags control block to all zeros.  */ | ||||
|     TX_MEMSET(group_ptr, 0, (sizeof(TX_EVENT_FLAGS_GROUP))); | ||||
|  | ||||
|     /* Setup the basic event flags group fields.  */ | ||||
|     group_ptr -> tx_event_flags_group_name =             name_ptr; | ||||
|  | ||||
|     /* Disable interrupts to put the event flags group on the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Setup the event flags ID to make it valid.  */ | ||||
|     group_ptr -> tx_event_flags_group_id =  TX_EVENT_FLAGS_ID; | ||||
|  | ||||
|     /* Place the group on the list of created event flag groups.  First, | ||||
|        check for an empty list.  */ | ||||
|     if (_tx_event_flags_created_count == TX_EMPTY) | ||||
|     { | ||||
|  | ||||
|         /* The created event flags list is empty.  Add event flag group to empty list.  */ | ||||
|         _tx_event_flags_created_ptr =                         group_ptr; | ||||
|         group_ptr -> tx_event_flags_group_created_next =      group_ptr; | ||||
|         group_ptr -> tx_event_flags_group_created_previous =  group_ptr; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* This list is not NULL, add to the end of the list.  */ | ||||
|         next_group =      _tx_event_flags_created_ptr; | ||||
|         previous_group =  next_group -> tx_event_flags_group_created_previous; | ||||
|  | ||||
|         /* Place the new event flag group in the list.  */ | ||||
|         next_group -> tx_event_flags_group_created_previous =  group_ptr; | ||||
|         previous_group -> tx_event_flags_group_created_next =  group_ptr; | ||||
|  | ||||
|         /* Setup this group's created links.  */ | ||||
|         group_ptr -> tx_event_flags_group_created_previous =  previous_group; | ||||
|         group_ptr -> tx_event_flags_group_created_next =      next_group; | ||||
|     } | ||||
|  | ||||
|     /* Increment the number of created event flag groups.  */ | ||||
|     _tx_event_flags_created_count++; | ||||
|  | ||||
|     /* Optional event flag group create extended processing.  */ | ||||
|     TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr) | ||||
|  | ||||
|     /* If trace is enabled, register this object.  */ | ||||
|     TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_EVENT_FLAGS, group_ptr, name_ptr, 0, 0) | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_CREATE, group_ptr, TX_POINTER_TO_ULONG_CONVERT(&next_group), 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_EVENT_FLAGS_CREATE_INSERT | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										209
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_delete.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_delete.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,209 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Event Flags                                                         */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_event_flags.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_event_flags_delete                              PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function deletes the specified event flag group.  All threads  */ | ||||
| /*    suspended on the group are resumed with the TX_DELETED status       */ | ||||
| /*    code.                                                               */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    group_ptr                         Pointer to group control block    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD               *thread_ptr; | ||||
| TX_THREAD               *next_thread; | ||||
| UINT                    suspended_count; | ||||
| TX_EVENT_FLAGS_GROUP    *next_group; | ||||
| TX_EVENT_FLAGS_GROUP    *previous_group; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to remove the group from the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_DELETE, group_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS) | ||||
|  | ||||
|     /* Optional event flags group delete extended processing.  */ | ||||
|     TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr) | ||||
|  | ||||
|     /* If trace is enabled, unregister this object.  */ | ||||
|     TX_TRACE_OBJECT_UNREGISTER(group_ptr) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_EVENT_FLAGS_DELETE_INSERT | ||||
|  | ||||
|     /* Clear the event flag group ID to make it invalid.  */ | ||||
|     group_ptr -> tx_event_flags_group_id =  TX_CLEAR_ID; | ||||
|  | ||||
|     /* Decrement the number of created event flag groups.  */ | ||||
|     _tx_event_flags_created_count--; | ||||
|  | ||||
|     /* See if this group is the only one on the list.  */ | ||||
|     if (_tx_event_flags_created_count == TX_EMPTY) | ||||
|     { | ||||
|  | ||||
|         /* Only created event flag group, just set the created list to NULL.  */ | ||||
|         _tx_event_flags_created_ptr =  TX_NULL; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Link-up the neighbors.  */ | ||||
|         next_group =                                           group_ptr -> tx_event_flags_group_created_next; | ||||
|         previous_group =                                       group_ptr -> tx_event_flags_group_created_previous; | ||||
|         next_group -> tx_event_flags_group_created_previous =  previous_group; | ||||
|         previous_group -> tx_event_flags_group_created_next =  next_group; | ||||
|  | ||||
|         /* See if we have to update the created list head pointer.  */ | ||||
|         if (_tx_event_flags_created_ptr == group_ptr) | ||||
|         { | ||||
|  | ||||
|             /* Yes, move the head pointer to the next link. */ | ||||
|             _tx_event_flags_created_ptr =  next_group; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Temporarily disable preemption.  */ | ||||
|     _tx_thread_preempt_disable++; | ||||
|  | ||||
|     /* Pickup the suspension information.  */ | ||||
|     thread_ptr =                                         group_ptr -> tx_event_flags_group_suspension_list; | ||||
|     group_ptr -> tx_event_flags_group_suspension_list =  TX_NULL; | ||||
|     suspended_count =                                    group_ptr -> tx_event_flags_group_suspended_count; | ||||
|     group_ptr -> tx_event_flags_group_suspended_count =  TX_NO_SUSPENSIONS; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Walk through the event flag suspension list to resume any and all threads | ||||
|        suspended on this group.  */ | ||||
|     while (suspended_count != TX_NO_SUSPENSIONS) | ||||
|     { | ||||
|  | ||||
|         /* Decrement the number of suspended threads.  */ | ||||
|         suspended_count--; | ||||
|  | ||||
|         /* Lockout interrupts.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* Clear the cleanup pointer, this prevents the timeout from doing | ||||
|            anything.  */ | ||||
|         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|         /* Set the return status in the thread to TX_DELETED.  */ | ||||
|         thread_ptr -> tx_thread_suspend_status =  TX_DELETED; | ||||
|  | ||||
|         /* Move the thread pointer ahead.  */ | ||||
|         next_thread =  thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Resume the thread!  */ | ||||
|         _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #else | ||||
|  | ||||
|         /* Temporarily disable preemption again.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Resume the thread.  */ | ||||
|         _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|         /* Move to next thread.  */ | ||||
|         thread_ptr =  next_thread; | ||||
|     } | ||||
|  | ||||
|     /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h.  */ | ||||
|     TX_EVENT_FLAGS_GROUP_DELETE_PORT_COMPLETION(group_ptr) | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Release previous preempt disable.  */ | ||||
|     _tx_thread_preempt_disable--; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Check for preemption.  */ | ||||
|     _tx_thread_system_preempt_check(); | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										407
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_get.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										407
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_get.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,407 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Event Flags                                                         */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_event_flags.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_event_flags_get                                 PORTABLE C      */ | ||||
| /*                                                           6.2.0        */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function gets the specified event flags from the group,        */ | ||||
| /*    according to the get option.  The get option also specifies whether */ | ||||
| /*    or not the retrieved flags are cleared.                             */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    group_ptr                         Pointer to group control block    */ | ||||
| /*    requested_event_flags             Event flags requested             */ | ||||
| /*    get_option                        Specifies and/or and clear options*/ | ||||
| /*    actual_flags_ptr                  Pointer to place the actual flags */ | ||||
| /*                                        the service retrieved           */ | ||||
| /*    wait_option                       Suspension option                 */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_suspend         Suspend thread service            */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020      William E. Lamie        Initial Version 6.0           */ | ||||
| /*  09-30-2020      Yuxin Zhou              Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*  04-25-2022      Scott Larson            Modified comment(s),          */ | ||||
| /*                                            handle 0 flags case,        */ | ||||
| /*                                            resulting in version 6.1.11 */ | ||||
| /*  10-31-2022      Scott Larson            Modified comment(s), always   */ | ||||
| /*                                            return actual flags,        */ | ||||
| /*                                            resulting in version 6.2.0  */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags, | ||||
|                     UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| UINT            status; | ||||
| UINT            and_request; | ||||
| UINT            clear_request; | ||||
| ULONG           current_flags; | ||||
| ULONG           flags_satisfied; | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
| ULONG           delayed_clear_flags; | ||||
| #endif | ||||
| UINT            suspended_count; | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
| UINT            interrupted_set_request; | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to examine the event flags group.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Increment the total event flags get counter.  */ | ||||
|     _tx_event_flags_performance_get_count++; | ||||
|  | ||||
|     /* Increment the number of event flags gets on this semaphore.  */ | ||||
|     group_ptr -> tx_event_flags_group__performance_get_count++; | ||||
| #endif | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_GET, group_ptr, requested_flags, group_ptr -> tx_event_flags_group_current, get_option, TX_TRACE_EVENT_FLAGS_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_EVENT_FLAGS_GET_INSERT | ||||
|  | ||||
|     /* Pickup current flags.  */ | ||||
|     current_flags =  group_ptr -> tx_event_flags_group_current; | ||||
|  | ||||
|     /* Return the actual event flags and apply delayed clearing.  */ | ||||
|     *actual_flags_ptr =  current_flags & ~group_ptr -> tx_event_flags_group_delayed_clear; | ||||
|  | ||||
|     /* Apply the event flag option mask.  */ | ||||
|     and_request =  (get_option & TX_AND); | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|     /* Check for AND condition. All flags must be present to satisfy request.  */ | ||||
|     if (and_request == TX_AND) | ||||
|     { | ||||
|  | ||||
|         /* AND request is present.  */ | ||||
|  | ||||
|         /* Calculate the flags present.  */ | ||||
|         flags_satisfied =  (current_flags & requested_flags); | ||||
|  | ||||
|         /* Determine if they satisfy the AND request.  */ | ||||
|         if (flags_satisfied != requested_flags) | ||||
|         { | ||||
|  | ||||
|             /* No, not all the requested flags are present. Clear the flags present variable.  */ | ||||
|             flags_satisfied =  ((ULONG) 0); | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* OR request is present. Simply or the requested flags and the current flags.  */ | ||||
|         flags_satisfied =  (current_flags & requested_flags); | ||||
|     } | ||||
|  | ||||
|     /* Determine if the request is satisfied.  */ | ||||
|     if (flags_satisfied != ((ULONG) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Pickup the clear bit.  */ | ||||
|         clear_request =  (get_option & TX_EVENT_FLAGS_CLEAR_MASK); | ||||
|  | ||||
|         /* Determine whether or not clearing needs to take place.  */ | ||||
|         if (clear_request == TX_TRUE) | ||||
|         { | ||||
|  | ||||
|              /* Yes, clear the flags that satisfied this request.  */ | ||||
|              group_ptr -> tx_event_flags_group_current = | ||||
|                                         group_ptr -> tx_event_flags_group_current & (~requested_flags); | ||||
|         } | ||||
|  | ||||
|         /* Return success.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|     } | ||||
|  | ||||
| #else | ||||
|  | ||||
|     /* Pickup delayed clear flags.  */ | ||||
|     delayed_clear_flags =  group_ptr -> tx_event_flags_group_delayed_clear; | ||||
|  | ||||
|     /* Determine if there are any delayed clear operations pending.  */ | ||||
|     if (delayed_clear_flags != ((ULONG) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Yes, apply them to the current flags.  */ | ||||
|         current_flags =  current_flags & (~delayed_clear_flags); | ||||
|     } | ||||
|  | ||||
|     /* Check for AND condition. All flags must be present to satisfy request.  */ | ||||
|     if (and_request == TX_AND) | ||||
|     { | ||||
|  | ||||
|         /* AND request is present.  */ | ||||
|  | ||||
|         /* Calculate the flags present.  */ | ||||
|         flags_satisfied =  (current_flags & requested_flags); | ||||
|  | ||||
|         /* Determine if they satisfy the AND request.  */ | ||||
|         if (flags_satisfied != requested_flags) | ||||
|         { | ||||
|  | ||||
|             /* No, not all the requested flags are present. Clear the flags present variable.  */ | ||||
|             flags_satisfied =  ((ULONG) 0); | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* OR request is present. Simply AND together the requested flags and the current flags | ||||
|            to see if any are present.  */ | ||||
|         flags_satisfied =  (current_flags & requested_flags); | ||||
|     } | ||||
|  | ||||
|     /* Determine if the request is satisfied.  */ | ||||
|     if (flags_satisfied != ((ULONG) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Yes, this request can be handled immediately.  */ | ||||
|  | ||||
|         /* Pickup the clear bit.  */ | ||||
|         clear_request =  (get_option & TX_EVENT_FLAGS_CLEAR_MASK); | ||||
|  | ||||
|         /* Determine whether or not clearing needs to take place.  */ | ||||
|         if (clear_request == TX_TRUE) | ||||
|         { | ||||
|  | ||||
|             /* Set interrupted set request flag to false.  */ | ||||
|             interrupted_set_request =  TX_FALSE; | ||||
|  | ||||
|             /* Determine if the suspension list is being processed by an interrupted | ||||
|                set request.  */ | ||||
|             if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS) | ||||
|             { | ||||
|  | ||||
|                 if (group_ptr -> tx_event_flags_group_suspension_list == TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     /* Set the interrupted set request flag.  */ | ||||
|                     interrupted_set_request =  TX_TRUE; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             /* Was a set request interrupted?  */ | ||||
|             if (interrupted_set_request == TX_TRUE) | ||||
|             { | ||||
|  | ||||
|                 /* A previous set operation is was interrupted, we need to defer the | ||||
|                    event clearing until the set operation is complete.  */ | ||||
|  | ||||
|                 /* Remember the events to clear.  */ | ||||
|                 group_ptr -> tx_event_flags_group_delayed_clear = | ||||
|                                         group_ptr -> tx_event_flags_group_delayed_clear | requested_flags; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Yes, clear the flags that satisfied this request.  */ | ||||
|                 group_ptr -> tx_event_flags_group_current = | ||||
|                                         group_ptr -> tx_event_flags_group_current & ~requested_flags; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Set status to success.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|     else | ||||
|     { | ||||
|         /* flags_satisfied is 0.  */ | ||||
|         /* Determine if the request specifies suspension.  */ | ||||
|         if (wait_option != TX_NO_WAIT) | ||||
|         { | ||||
|  | ||||
|             /* Determine if the preempt disable flag is non-zero OR the requested events is 0.  */ | ||||
|             if ((_tx_thread_preempt_disable != ((UINT) 0)) || (requested_flags == (UINT) 0)) | ||||
|             { | ||||
|  | ||||
|                 /* Suspension is not allowed if the preempt disable flag is non-zero at this point, | ||||
|                    or if requested_flags is 0, return error completion.  */ | ||||
|                 status =  TX_NO_EVENTS; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Prepare for suspension of this thread.  */ | ||||
|  | ||||
| #ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                 /* Increment the total event flags suspensions counter.  */ | ||||
|                 _tx_event_flags_performance_suspension_count++; | ||||
|  | ||||
|                 /* Increment the number of event flags suspensions on this semaphore.  */ | ||||
|                 group_ptr -> tx_event_flags_group___performance_suspension_count++; | ||||
| #endif | ||||
|  | ||||
|                 /* Pickup thread pointer.  */ | ||||
|                 TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
|                 /* Setup cleanup routine pointer.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_cleanup =  &(_tx_event_flags_cleanup); | ||||
|  | ||||
|                 /* Remember which event flags we are looking for.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_info =  requested_flags; | ||||
|  | ||||
|                 /* Save the get option as well.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_option =  get_option; | ||||
|  | ||||
|                 /* Save the destination for the current events.  */ | ||||
|                 thread_ptr -> tx_thread_additional_suspend_info =  (VOID *) actual_flags_ptr; | ||||
|  | ||||
|                 /* Setup cleanup information, i.e. this event flags group control | ||||
|                    block.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_control_block =  (VOID *) group_ptr; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                 /* Increment the suspension sequence number, which is used to identify | ||||
|                    this suspension event.  */ | ||||
|                 thread_ptr -> tx_thread_suspension_sequence++; | ||||
| #endif | ||||
|  | ||||
|                 /* Pickup the suspended count.  */ | ||||
|                 suspended_count =  group_ptr -> tx_event_flags_group_suspended_count; | ||||
|  | ||||
|                 /* Setup suspension list.  */ | ||||
|                 if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|                 { | ||||
|  | ||||
|                     /* No other threads are suspended.  Setup the head pointer and | ||||
|                        just setup this threads pointers to itself.  */ | ||||
|                     group_ptr -> tx_event_flags_group_suspension_list =   thread_ptr; | ||||
|                     thread_ptr -> tx_thread_suspended_next =              thread_ptr; | ||||
|                     thread_ptr -> tx_thread_suspended_previous =          thread_ptr; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* This list is not NULL, add current thread to the end. */ | ||||
|                     next_thread =                                   group_ptr -> tx_event_flags_group_suspension_list; | ||||
|                     thread_ptr -> tx_thread_suspended_next =        next_thread; | ||||
|                     previous_thread =                               next_thread -> tx_thread_suspended_previous; | ||||
|                     thread_ptr -> tx_thread_suspended_previous =    previous_thread; | ||||
|                     previous_thread -> tx_thread_suspended_next =   thread_ptr; | ||||
|                     next_thread -> tx_thread_suspended_previous =   thread_ptr; | ||||
|                 } | ||||
|  | ||||
|                 /* Increment the number of threads suspended.  */ | ||||
|                 group_ptr -> tx_event_flags_group_suspended_count++; | ||||
|  | ||||
|                 /* Set the state to suspended.  */ | ||||
|                 thread_ptr -> tx_thread_state =    TX_EVENT_FLAG; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                 /* Call actual non-interruptable thread suspension routine.  */ | ||||
|                 _tx_thread_system_ni_suspend(thread_ptr, wait_option); | ||||
|  | ||||
|                 /* Return the completion status.  */ | ||||
|                 status =  thread_ptr -> tx_thread_suspend_status; | ||||
| #else | ||||
|  | ||||
|                 /* Set the suspending flag.  */ | ||||
|                 thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|                 /* Setup the timeout period.  */ | ||||
|                 thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  wait_option; | ||||
|  | ||||
|                 /* Temporarily disable preemption.  */ | ||||
|                 _tx_thread_preempt_disable++; | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Call actual thread suspension routine.  */ | ||||
|                 _tx_thread_system_suspend(thread_ptr); | ||||
|  | ||||
|                 /* Disable interrupts.  */ | ||||
|                 TX_DISABLE | ||||
|  | ||||
|                 /* Return the completion status.  */ | ||||
|                 status =  thread_ptr -> tx_thread_suspend_status; | ||||
| #endif | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Immediate return, return error completion.  */ | ||||
|             status =  TX_NO_EVENTS; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										145
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_info_get.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_info_get.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Event Flags                                                         */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_event_flags.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_event_flags_info_get                            PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function retrieves information from the specified event flag   */ | ||||
| /*    group.                                                              */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    group_ptr                         Pointer to event flag group       */ | ||||
| /*    name                              Destination for the event flag    */ | ||||
| /*                                        group name                      */ | ||||
| /*    current_flags                     Current event flags               */ | ||||
| /*    first_suspended                   Destination for pointer of first  */ | ||||
| /*                                        thread suspended on event flags */ | ||||
| /*    suspended_count                   Destination for suspended count   */ | ||||
| /*    next_group                        Destination for pointer to next   */ | ||||
| /*                                        event flag group on the created */ | ||||
| /*                                        list                            */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags, | ||||
|                     TX_THREAD **first_suspended, ULONG *suspended_count, | ||||
|                     TX_EVENT_FLAGS_GROUP **next_group) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_INFO_GET, group_ptr, 0, 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_EVENT_FLAGS_INFO_GET_INSERT | ||||
|  | ||||
|     /* Retrieve all the pertinent information and return it in the supplied | ||||
|        destinations.  */ | ||||
|  | ||||
|     /* Retrieve the name of the event flag group.  */ | ||||
|     if (name != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *name =  group_ptr -> tx_event_flags_group_name; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the current event flags in the event flag group.  */ | ||||
|     if (current_flags != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Pickup the current flags and apply delayed clearing.  */ | ||||
|         *current_flags =  group_ptr -> tx_event_flags_group_current & | ||||
|                                                         ~group_ptr -> tx_event_flags_group_delayed_clear; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the first thread suspended on this event flag group.  */ | ||||
|     if (first_suspended != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *first_suspended =  group_ptr -> tx_event_flags_group_suspension_list; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the number of threads suspended on this event flag group.  */ | ||||
|     if (suspended_count != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *suspended_count =  (ULONG) group_ptr -> tx_event_flags_group_suspended_count; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the pointer to the next event flag group created.  */ | ||||
|     if (next_group != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *next_group =  group_ptr -> tx_event_flags_group_created_next; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										134
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_initialize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_initialize.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Event Flags                                                         */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_event_flags.h" | ||||
|  | ||||
|  | ||||
| #ifndef TX_INLINE_INITIALIZATION | ||||
|  | ||||
| /* Locate event flags component data in this file.  */ | ||||
| /* Define the head pointer of the created event flags list.  */ | ||||
|  | ||||
| TX_EVENT_FLAGS_GROUP * _tx_event_flags_created_ptr; | ||||
|  | ||||
|  | ||||
| /* Define the variable that holds the number of created event flag groups. */ | ||||
|  | ||||
| ULONG                  _tx_event_flags_created_count; | ||||
|  | ||||
|  | ||||
| #ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
| /* Define the total number of event flag sets.  */ | ||||
|  | ||||
| ULONG                  _tx_event_flags_performance_set_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of event flag gets.  */ | ||||
|  | ||||
| ULONG                  _tx_event_flags_performance_get_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of event flag suspensions.  */ | ||||
|  | ||||
| ULONG                  _tx_event_flags_performance_suspension_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of event flag timeouts.  */ | ||||
|  | ||||
| ULONG                  _tx_event_flags_performance_timeout_count; | ||||
|  | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_event_flags_initialize                          PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function initializes the various control data structures for   */ | ||||
| /*    the event flags component.                                          */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_initialize_high_level         High level initialization         */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            opt out of function when    */ | ||||
| /*                                            TX_INLINE_INITIALIZATION is */ | ||||
| /*                                            defined,                    */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_event_flags_initialize(VOID) | ||||
| { | ||||
|  | ||||
| #ifndef TX_DISABLE_REDUNDANT_CLEARING | ||||
|  | ||||
|     /* Initialize the head pointer of the created event flags list and the | ||||
|        number of event flags created.  */ | ||||
|     _tx_event_flags_created_ptr =        TX_NULL; | ||||
|     _tx_event_flags_created_count =      TX_EMPTY; | ||||
|  | ||||
| #ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Initialize event flags performance counters.  */ | ||||
|     _tx_event_flags_performance_set_count =         ((ULONG) 0); | ||||
|     _tx_event_flags_performance_get_count =         ((ULONG) 0); | ||||
|     _tx_event_flags_performance_suspension_count =  ((ULONG) 0); | ||||
|     _tx_event_flags_performance_timeout_count =     ((ULONG) 0); | ||||
| #endif | ||||
| #endif | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										625
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_set.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										625
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_set.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,625 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Event Flags                                                         */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_event_flags.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_event_flags_set                                 PORTABLE C      */ | ||||
| /*                                                           6.1.11       */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function sets the specified flags in the event group based on  */ | ||||
| /*    the set option specified.  All threads suspended on the group whose */ | ||||
| /*    get request can now be satisfied are resumed.                       */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    group_ptr                         Pointer to group control block    */ | ||||
| /*    flags_to_set                      Event flags to set                */ | ||||
| /*    set_option                        Specified either AND or OR        */ | ||||
| /*                                        operation on the event flags    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Always returns success            */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020      William E. Lamie        Initial Version 6.0           */ | ||||
| /*  09-30-2020      Yuxin Zhou              Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*  04-25-2022      William E. Lamie        Modified comment(s), and      */ | ||||
| /*                                            added corrected preemption  */ | ||||
| /*                                            check logic, resulting in   */ | ||||
| /*                                            version 6.1.11              */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set, UINT set_option) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_THREAD       *next_thread_ptr; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| TX_THREAD       *satisfied_list; | ||||
| TX_THREAD       *last_satisfied; | ||||
| TX_THREAD       *suspended_list; | ||||
| UINT            suspended_count; | ||||
| ULONG           current_event_flags; | ||||
| ULONG           requested_flags; | ||||
| ULONG           flags_satisfied; | ||||
| ULONG           *suspend_info_ptr; | ||||
| UINT            and_request; | ||||
| UINT            get_option; | ||||
| UINT            clear_request; | ||||
| UINT            preempt_check; | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
| UINT            interrupted_set_request; | ||||
| #endif | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
| VOID            (*events_set_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *notify_group_ptr); | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to remove the semaphore from the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Increment the total event flags set counter.  */ | ||||
|     _tx_event_flags_performance_set_count++; | ||||
|  | ||||
|     /* Increment the number of event flags sets on this semaphore.  */ | ||||
|     group_ptr -> tx_event_flags_group_performance_set_count++; | ||||
| #endif | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_SET, group_ptr, flags_to_set, set_option, group_ptr -> tx_event_flags_group_suspended_count, TX_TRACE_EVENT_FLAGS_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_EVENT_FLAGS_SET_INSERT | ||||
|  | ||||
|     /* Determine how to set this group's event flags.  */ | ||||
|     if ((set_option & TX_EVENT_FLAGS_AND_MASK) == TX_AND) | ||||
|     { | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Set interrupted set request flag to false.  */ | ||||
|         interrupted_set_request =  TX_FALSE; | ||||
|  | ||||
|         /* Determine if the suspension list is being processed by an interrupted | ||||
|            set request.  */ | ||||
|         if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS) | ||||
|         { | ||||
|  | ||||
|             if (group_ptr -> tx_event_flags_group_suspension_list == TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Set the interrupted set request flag.  */ | ||||
|                 interrupted_set_request =  TX_TRUE; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Was a set request interrupted?  */ | ||||
|         if (interrupted_set_request == TX_TRUE) | ||||
|         { | ||||
|  | ||||
|             /* A previous set operation was interrupted, we need to defer the | ||||
|                event clearing until the set operation is complete.  */ | ||||
|  | ||||
|             /* Remember the events to clear.  */ | ||||
|             group_ptr -> tx_event_flags_group_delayed_clear = | ||||
|                                         group_ptr -> tx_event_flags_group_delayed_clear | ~flags_to_set; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
| #endif | ||||
|  | ||||
|             /* Previous set operation was not interrupted, simply clear the | ||||
|                specified flags by "ANDing" the flags into the current events | ||||
|                of the group.  */ | ||||
|             group_ptr -> tx_event_flags_group_current = | ||||
|                 group_ptr -> tx_event_flags_group_current & flags_to_set; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         } | ||||
| #endif | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|         /* Pickup the notify callback routine for this event flag group.  */ | ||||
|         events_set_notify =  group_ptr -> tx_event_flags_group_set_notify; | ||||
| #endif | ||||
|  | ||||
|         /* "OR" the flags into the current events of the group.  */ | ||||
|         group_ptr -> tx_event_flags_group_current = | ||||
|             group_ptr -> tx_event_flags_group_current | flags_to_set; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Determine if there are any delayed flags to clear.  */ | ||||
|         if (group_ptr -> tx_event_flags_group_delayed_clear != ((ULONG) 0)) | ||||
|         { | ||||
|  | ||||
|             /* Yes, we need to neutralize the delayed clearing as well.  */ | ||||
|             group_ptr -> tx_event_flags_group_delayed_clear = | ||||
|                                         group_ptr -> tx_event_flags_group_delayed_clear & ~flags_to_set; | ||||
|         } | ||||
| #endif | ||||
|  | ||||
|         /* Clear the preempt check flag.  */ | ||||
|         preempt_check =  TX_FALSE; | ||||
|  | ||||
|         /* Pickup the thread suspended count.  */ | ||||
|         suspended_count =  group_ptr -> tx_event_flags_group_suspended_count; | ||||
|  | ||||
|         /* Determine if there are any threads suspended on the event flag group.  */ | ||||
|         if (group_ptr -> tx_event_flags_group_suspension_list != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Determine if there is just a single thread waiting on the event | ||||
|                flag group.  */ | ||||
|             if (suspended_count == ((UINT) 1)) | ||||
|             { | ||||
|  | ||||
|                 /* Single thread waiting for event flags.  Bypass the multiple thread | ||||
|                    logic.  */ | ||||
|  | ||||
|                 /* Setup thread pointer.  */ | ||||
|                 thread_ptr =  group_ptr -> tx_event_flags_group_suspension_list; | ||||
|  | ||||
|                 /* Pickup the current event flags.  */ | ||||
|                 current_event_flags =  group_ptr -> tx_event_flags_group_current; | ||||
|  | ||||
|                 /* Pickup the suspend information.  */ | ||||
|                 requested_flags =  thread_ptr -> tx_thread_suspend_info; | ||||
|  | ||||
|                 /* Pickup the suspend option.  */ | ||||
|                 get_option =  thread_ptr -> tx_thread_suspend_option; | ||||
|  | ||||
|                 /* Isolate the AND selection.  */ | ||||
|                 and_request =  (get_option & TX_AND); | ||||
|  | ||||
|                 /* Check for AND condition. All flags must be present to satisfy request.  */ | ||||
|                 if (and_request == TX_AND) | ||||
|                 { | ||||
|  | ||||
|                     /* AND request is present.  */ | ||||
|  | ||||
|                     /* Calculate the flags present.  */ | ||||
|                     flags_satisfied =  (current_event_flags & requested_flags); | ||||
|  | ||||
|                     /* Determine if they satisfy the AND request.  */ | ||||
|                     if (flags_satisfied != requested_flags) | ||||
|                     { | ||||
|  | ||||
|                         /* No, not all the requested flags are present. Clear the flags present variable.  */ | ||||
|                         flags_satisfied =  ((ULONG) 0); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* OR request is present. Simply or the requested flags and the current flags.  */ | ||||
|                     flags_satisfied =  (current_event_flags & requested_flags); | ||||
|                 } | ||||
|  | ||||
|                 /* Determine if the request is satisfied.  */ | ||||
|                 if (flags_satisfied != ((ULONG) 0)) | ||||
|                 { | ||||
|  | ||||
|                     /* Yes, resume the thread and apply any event flag | ||||
|                        clearing.  */ | ||||
|  | ||||
|                     /* Return the actual event flags that satisfied the request.  */ | ||||
|                     suspend_info_ptr =   TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info); | ||||
|                     *suspend_info_ptr =  current_event_flags; | ||||
|  | ||||
|                     /* Pickup the clear bit.  */ | ||||
|                     clear_request =  (get_option & TX_EVENT_FLAGS_CLEAR_MASK); | ||||
|  | ||||
|                     /* Determine whether or not clearing needs to take place.  */ | ||||
|                     if (clear_request == TX_TRUE) | ||||
|                     { | ||||
|  | ||||
|                         /* Yes, clear the flags that satisfied this request.  */ | ||||
|                         group_ptr -> tx_event_flags_group_current =  group_ptr -> tx_event_flags_group_current & (~requested_flags); | ||||
|                     } | ||||
|  | ||||
|                     /* Clear the suspension information in the event flag group.  */ | ||||
|                     group_ptr -> tx_event_flags_group_suspension_list =  TX_NULL; | ||||
|                     group_ptr -> tx_event_flags_group_suspended_count =  TX_NO_SUSPENSIONS; | ||||
|  | ||||
|                     /* Clear cleanup routine to avoid timeout.  */ | ||||
|                     thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|                     /* Put return status into the thread control block.  */ | ||||
|                     thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                     /* Resume the thread!  */ | ||||
|                     _tx_thread_system_ni_resume(thread_ptr); | ||||
| #else | ||||
|  | ||||
|                     /* Temporarily disable preemption.  */ | ||||
|                     _tx_thread_preempt_disable++; | ||||
|  | ||||
|                     /* Restore interrupts.  */ | ||||
|                     TX_RESTORE | ||||
|  | ||||
|                     /* Resume thread.  */ | ||||
|                     _tx_thread_system_resume(thread_ptr); | ||||
|  | ||||
|                     /* Disable interrupts to remove the semaphore from the created list.  */ | ||||
|                     TX_DISABLE | ||||
| #endif | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Otherwise, the event flag requests of multiple threads must be | ||||
|                    examined.  */ | ||||
|  | ||||
|                 /* Setup thread pointer, keep a local copy of the head pointer.  */ | ||||
|                 suspended_list =  group_ptr -> tx_event_flags_group_suspension_list; | ||||
|                 thread_ptr =      suspended_list; | ||||
|  | ||||
|                 /* Clear the suspended list head pointer to thwart manipulation of | ||||
|                    the list in ISR's while we are processing here.  */ | ||||
|                 group_ptr -> tx_event_flags_group_suspension_list =  TX_NULL; | ||||
|  | ||||
|                 /* Setup the satisfied thread pointers.  */ | ||||
|                 satisfied_list =  TX_NULL; | ||||
|                 last_satisfied =  TX_NULL; | ||||
|  | ||||
|                 /* Pickup the current event flags.  */ | ||||
|                 current_event_flags =  group_ptr -> tx_event_flags_group_current; | ||||
|  | ||||
|                 /* Disable preemption while we process the suspended list.  */ | ||||
|                 _tx_thread_preempt_disable++; | ||||
|  | ||||
|                 /* Since we have temporarily disabled preemption globally, set the preempt  | ||||
|                    check flag to check for any preemption condition - including from  | ||||
|                    unrelated ISR processing.  */ | ||||
|                 preempt_check =  TX_TRUE; | ||||
|  | ||||
|                 /* Loop to examine all of the suspended threads. */ | ||||
|                 do | ||||
|                 { | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                     /* Restore interrupts temporarily.  */ | ||||
|                     TX_RESTORE | ||||
|  | ||||
|                     /* Disable interrupts again.  */ | ||||
|                     TX_DISABLE | ||||
| #endif | ||||
|  | ||||
|                     /* Determine if we need to reset the search.  */ | ||||
|                     if (group_ptr -> tx_event_flags_group_reset_search != TX_FALSE) | ||||
|                     { | ||||
|  | ||||
|                         /* Clear the reset search flag.  */ | ||||
|                         group_ptr -> tx_event_flags_group_reset_search =  TX_FALSE; | ||||
|  | ||||
|                         /* Move the thread pointer to the beginning of the search list.  */ | ||||
|                         thread_ptr =  suspended_list; | ||||
|  | ||||
|                         /* Reset the suspended count.  */ | ||||
|                         suspended_count =  group_ptr -> tx_event_flags_group_suspended_count; | ||||
|  | ||||
|                         /* Update the current events with any new ones that might | ||||
|                            have been set in a nested set events call from an ISR.  */ | ||||
|                         current_event_flags =  current_event_flags | group_ptr -> tx_event_flags_group_current; | ||||
|                     } | ||||
|  | ||||
|                     /* Save next thread pointer.  */ | ||||
|                     next_thread_ptr =  thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|                     /* Pickup the suspend information.  */ | ||||
|                     requested_flags =  thread_ptr -> tx_thread_suspend_info; | ||||
|  | ||||
|                     /* Pickup this thread's suspension get option.  */ | ||||
|                     get_option =  thread_ptr -> tx_thread_suspend_option; | ||||
|  | ||||
|                     /* Isolate the AND selection.  */ | ||||
|                     and_request =  (get_option & TX_AND); | ||||
|  | ||||
|                     /* Check for AND condition. All flags must be present to satisfy request.  */ | ||||
|                     if (and_request == TX_AND) | ||||
|                     { | ||||
|  | ||||
|                         /* AND request is present.  */ | ||||
|  | ||||
|                         /* Calculate the flags present.  */ | ||||
|                         flags_satisfied =  (current_event_flags & requested_flags); | ||||
|  | ||||
|                         /* Determine if they satisfy the AND request.  */ | ||||
|                         if (flags_satisfied != requested_flags) | ||||
|                         { | ||||
|  | ||||
|                             /* No, not all the requested flags are present. Clear the flags present variable.  */ | ||||
|                             flags_satisfied =  ((ULONG) 0); | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|  | ||||
|                         /* OR request is present. Simply or the requested flags and the current flags.  */ | ||||
|                         flags_satisfied =  (current_event_flags & requested_flags); | ||||
|                     } | ||||
|  | ||||
|                     /* Check to see if the thread had a timeout or wait abort during the event search processing. | ||||
|                        If so, just set the flags satisfied to ensure the processing here removes the thread from | ||||
|                        the suspension list.  */ | ||||
|                     if (thread_ptr -> tx_thread_state != TX_EVENT_FLAG) | ||||
|                     { | ||||
|  | ||||
|                        /* Simply set the satisfied flags to 1 in order to remove the thread from the suspension list.  */ | ||||
|                         flags_satisfied =  ((ULONG) 1); | ||||
|                     } | ||||
|  | ||||
|                     /* Determine if the request is satisfied.  */ | ||||
|                     if (flags_satisfied != ((ULONG) 0)) | ||||
|                     { | ||||
|  | ||||
|                         /* Yes, this request can be handled now.  */ | ||||
|  | ||||
|                         /* Determine if the thread is still suspended on the event flag group. If not, a wait | ||||
|                            abort must have been done from an ISR.  */ | ||||
|                         if (thread_ptr -> tx_thread_state == TX_EVENT_FLAG) | ||||
|                         { | ||||
|  | ||||
|                             /* Return the actual event flags that satisfied the request.  */ | ||||
|                             suspend_info_ptr =   TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info); | ||||
|                             *suspend_info_ptr =  current_event_flags; | ||||
|  | ||||
|                             /* Pickup the clear bit.  */ | ||||
|                             clear_request =  (get_option & TX_EVENT_FLAGS_CLEAR_MASK); | ||||
|  | ||||
|                             /* Determine whether or not clearing needs to take place.  */ | ||||
|                             if (clear_request == TX_TRUE) | ||||
|                             { | ||||
|  | ||||
|                                 /* Yes, clear the flags that satisfied this request.  */ | ||||
|                                 group_ptr -> tx_event_flags_group_current =  group_ptr -> tx_event_flags_group_current & ~requested_flags; | ||||
|                             } | ||||
|  | ||||
|                             /* Prepare for resumption of the first thread.  */ | ||||
|  | ||||
|                             /* Clear cleanup routine to avoid timeout.  */ | ||||
|                             thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|                             /* Put return status into the thread control block.  */ | ||||
|                             thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS; | ||||
|                         } | ||||
|  | ||||
|                         /* We need to remove the thread from the suspension list and place it in the | ||||
|                            expired list.  */ | ||||
|  | ||||
|                         /* See if this is the only suspended thread on the list.  */ | ||||
|                         if (thread_ptr == thread_ptr -> tx_thread_suspended_next) | ||||
|                         { | ||||
|  | ||||
|                             /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|                             /* Update the head pointer.  */ | ||||
|                             suspended_list =  TX_NULL; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* At least one more thread is on the same expiration list.  */ | ||||
|  | ||||
|                             /* Update the links of the adjacent threads.  */ | ||||
|                             next_thread =                                  thread_ptr -> tx_thread_suspended_next; | ||||
|                             previous_thread =                              thread_ptr -> tx_thread_suspended_previous; | ||||
|                             next_thread -> tx_thread_suspended_previous =  previous_thread; | ||||
|                             previous_thread -> tx_thread_suspended_next =  next_thread; | ||||
|  | ||||
|                             /* Update the list head pointer, if removing the head of the | ||||
|                                list.  */ | ||||
|                             if (suspended_list == thread_ptr) | ||||
|                             { | ||||
|  | ||||
|                                 /* Yes, head pointer needs to be updated.  */ | ||||
|                                 suspended_list =  thread_ptr -> tx_thread_suspended_next; | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         /* Decrement the suspension count.  */ | ||||
|                         group_ptr -> tx_event_flags_group_suspended_count--; | ||||
|  | ||||
|                         /* Place this thread on the expired list.  */ | ||||
|                         if (satisfied_list == TX_NULL) | ||||
|                         { | ||||
|  | ||||
|                             /* First thread on the satisfied list.  */ | ||||
|                             satisfied_list =  thread_ptr; | ||||
|                             last_satisfied =  thread_ptr; | ||||
|  | ||||
|                             /* Setup initial next pointer.  */ | ||||
|                             thread_ptr -> tx_thread_suspended_next =  TX_NULL; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* Not the first thread on the satisfied list.  */ | ||||
|  | ||||
|                             /* Link it up at the end.  */ | ||||
|                             last_satisfied -> tx_thread_suspended_next =  thread_ptr; | ||||
|                             thread_ptr -> tx_thread_suspended_next =      TX_NULL; | ||||
|                             last_satisfied =                              thread_ptr; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     /* Copy next thread pointer to working thread ptr.  */ | ||||
|                     thread_ptr =  next_thread_ptr; | ||||
|  | ||||
|                     /* Decrement the suspension count.  */ | ||||
|                     suspended_count--; | ||||
|  | ||||
|                 } while (suspended_count != TX_NO_SUSPENSIONS); | ||||
|  | ||||
|                 /* Setup the group's suspension list head again.  */ | ||||
|                 group_ptr -> tx_event_flags_group_suspension_list =  suspended_list; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                 /* Determine if there is any delayed event clearing to perform.  */ | ||||
|                 if (group_ptr -> tx_event_flags_group_delayed_clear != ((ULONG) 0)) | ||||
|                 { | ||||
|  | ||||
|                     /* Perform the delayed event clearing.  */ | ||||
|                     group_ptr -> tx_event_flags_group_current = | ||||
|                         group_ptr -> tx_event_flags_group_current & ~(group_ptr -> tx_event_flags_group_delayed_clear); | ||||
|  | ||||
|                     /* Clear the delayed event flag clear value.  */ | ||||
|                     group_ptr -> tx_event_flags_group_delayed_clear =  ((ULONG) 0); | ||||
|                 } | ||||
| #endif | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Walk through the satisfied list, setup initial thread pointer. */ | ||||
|                 thread_ptr =  satisfied_list; | ||||
|                 while(thread_ptr != TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     /* Get next pointer first.  */ | ||||
|                     next_thread_ptr =  thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|                     /* Disable interrupts.  */ | ||||
|                     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                     /* Resume the thread!  */ | ||||
|                     _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|                     /* Restore interrupts.  */ | ||||
|                     TX_RESTORE | ||||
| #else | ||||
|  | ||||
|                     /* Disable preemption again.  */ | ||||
|                     _tx_thread_preempt_disable++; | ||||
|  | ||||
|                     /* Restore interrupt posture.  */ | ||||
|                     TX_RESTORE | ||||
|  | ||||
|                     /* Resume the thread.  */ | ||||
|                     _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|                     /* Move next thread to current.  */ | ||||
|                     thread_ptr =  next_thread_ptr; | ||||
|                 } | ||||
|  | ||||
|                 /* Disable interrupts.  */ | ||||
|                 TX_DISABLE | ||||
|  | ||||
|                 /* Release thread preemption disable.  */ | ||||
|                 _tx_thread_preempt_disable--; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Determine if we need to set the reset search field.  */ | ||||
|             if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS) | ||||
|             { | ||||
|  | ||||
|                 /* We interrupted a search of an event flag group suspension | ||||
|                    list.  Make sure we reset the search.  */ | ||||
|                 group_ptr -> tx_event_flags_group_reset_search =  TX_TRUE; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|         /* Determine if a notify callback is required.  */ | ||||
|         if (events_set_notify != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Call application event flags set notification.  */ | ||||
|             (events_set_notify)(group_ptr); | ||||
|         } | ||||
| #endif | ||||
|  | ||||
|         /* Determine if a check for preemption is necessary.  */ | ||||
|         if (preempt_check == TX_TRUE) | ||||
|         { | ||||
|  | ||||
|             /* Yes, one or more threads were resumed, check for preemption.  */ | ||||
|             _tx_thread_system_preempt_check(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										109
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_set_notify.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								Middlewares/ST/threadx/common/src/tx_event_flags_set_notify.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Event Flags                                                         */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_event_flags.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_event_flags_set_notify                          PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function registers an application callback function that is    */ | ||||
| /*    called whenever an event flag is set in this group.                 */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    group_ptr                             Pointer to group control block*/ | ||||
| /*    group_put_notify                      Application callback function */ | ||||
| /*                                            (TX_NULL disables notify)   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Service return status         */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_event_flags_set_notify(TX_EVENT_FLAGS_GROUP *group_ptr, VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)) | ||||
| { | ||||
|  | ||||
| #ifdef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|     TX_EVENT_FLAGS_GROUP_NOT_USED(group_ptr); | ||||
|     TX_EVENT_FLAGS_SET_NOTIFY_NOT_USED(events_set_notify); | ||||
|  | ||||
|     /* Feature is not enabled, return error.  */ | ||||
|     return(TX_FEATURE_NOT_ENABLED); | ||||
| #else | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Make entry in event log.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_SET_NOTIFY, group_ptr, 0, 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS) | ||||
|  | ||||
|     /* Make entry in event log.  */ | ||||
|     TX_EL_EVENT_FLAGS_SET_NOTIFY_INSERT | ||||
|  | ||||
|     /* Setup event flag group set notification callback function.  */ | ||||
|     group_ptr -> tx_event_flags_group_set_notify =  events_set_notify; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return success to caller.  */ | ||||
|     return(TX_SUCCESS); | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										152
									
								
								Middlewares/ST/threadx/common/src/tx_initialize_high_level.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								Middlewares/ST/threadx/common/src/tx_initialize_high_level.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,152 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Initialize                                                          */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
|  | ||||
| /* Determine if in-line initialization is required.  */ | ||||
| #ifdef TX_INLINE_INITIALIZATION | ||||
| #define TX_INVOKE_INLINE_INITIALIZATION | ||||
| #endif | ||||
|  | ||||
| #include "tx_initialize.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_timer.h" | ||||
| #include "tx_semaphore.h" | ||||
| #include "tx_queue.h" | ||||
| #include "tx_event_flags.h" | ||||
| #include "tx_mutex.h" | ||||
| #include "tx_block_pool.h" | ||||
| #include "tx_byte_pool.h" | ||||
|  | ||||
|  | ||||
| /* Define the unused memory pointer.  The value of the first available | ||||
|    memory address is placed in this variable in the low-level | ||||
|    initialization function.  The content of this variable is passed | ||||
|    to the application's system definition function.  */ | ||||
|  | ||||
| VOID     *_tx_initialize_unused_memory; | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_initialize_high_level                           PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function is responsible for initializing all of the other      */ | ||||
| /*    components in the ThreadX real-time kernel.                         */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_initialize             Initialize the thread control     */ | ||||
| /*                                        component                       */ | ||||
| /*    _tx_timer_initialize              Initialize the timer control      */ | ||||
| /*                                        component                       */ | ||||
| /*    _tx_semaphore_initialize          Initialize the semaphore control  */ | ||||
| /*                                        component                       */ | ||||
| /*    _tx_queue_initialize              Initialize the queue control      */ | ||||
| /*                                        component                       */ | ||||
| /*    _tx_event_flags_initialize        Initialize the event flags control*/ | ||||
| /*                                        component                       */ | ||||
| /*    _tx_block_pool_initialize         Initialize the block pool control */ | ||||
| /*                                        component                       */ | ||||
| /*    _tx_byte_pool_initialize          Initialize the byte pool control  */ | ||||
| /*                                        component                       */ | ||||
| /*    _tx_mutex_initialize              Initialize the mutex control      */ | ||||
| /*                                        component                       */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_initialize_kernel_enter       Kernel entry function             */ | ||||
| /*    _tx_initialize_kernel_setup       Early kernel setup function that  */ | ||||
| /*                                        is optionally called by         */ | ||||
| /*                                        compiler's startup code.        */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID    _tx_initialize_high_level(VOID) | ||||
| { | ||||
|  | ||||
|     /* Initialize event tracing, if enabled.  */ | ||||
|     TX_TRACE_INITIALIZE | ||||
|  | ||||
|     /* Initialize the event log, if enabled.  */ | ||||
|     TX_EL_INITIALIZE | ||||
|  | ||||
|     /* Call the thread control initialization function.  */ | ||||
|     _tx_thread_initialize(); | ||||
|  | ||||
| #ifndef TX_NO_TIMER | ||||
|  | ||||
|     /* Call the timer control initialization function.  */ | ||||
|     _tx_timer_initialize(); | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_DISABLE_REDUNDANT_CLEARING | ||||
|  | ||||
|     /* Call the semaphore initialization function.  */ | ||||
|     _tx_semaphore_initialize(); | ||||
|  | ||||
|     /* Call the queue initialization function.  */ | ||||
|     _tx_queue_initialize(); | ||||
|  | ||||
|     /* Call the event flag initialization function.  */ | ||||
|     _tx_event_flags_initialize(); | ||||
|  | ||||
|     /* Call the block pool initialization function.  */ | ||||
|     _tx_block_pool_initialize(); | ||||
|  | ||||
|     /* Call the byte pool initialization function.  */ | ||||
|     _tx_byte_pool_initialize(); | ||||
|  | ||||
|     /* Call the mutex initialization function.  */ | ||||
|     _tx_mutex_initialize(); | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										168
									
								
								Middlewares/ST/threadx/common/src/tx_initialize_kernel_enter.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								Middlewares/ST/threadx/common/src/tx_initialize_kernel_enter.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,168 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Initialize                                                          */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_initialize.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
| #if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) | ||||
| extern VOID _tx_execution_initialize(VOID); | ||||
| #endif | ||||
|  | ||||
| /* Define any port-specific scheduling data structures.  */ | ||||
|  | ||||
| TX_PORT_SPECIFIC_DATA | ||||
|  | ||||
|  | ||||
| #ifdef TX_SAFETY_CRITICAL | ||||
| TX_SAFETY_CRITICAL_EXCEPTION_HANDLER | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_initialize_kernel_enter                         PORTABLE C      */ | ||||
| /*                                                           6.3.0        */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function is the first ThreadX function called during           */ | ||||
| /*    initialization.  It is called from the application's "main()"       */ | ||||
| /*    function.  It is important to note that this routine never          */ | ||||
| /*    returns.  The processing of this function is relatively simple:     */ | ||||
| /*    it calls several ThreadX initialization functions (if needed),      */ | ||||
| /*    calls the application define function, and then invokes the         */ | ||||
| /*    scheduler.                                                          */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_initialize_low_level          Low-level initialization          */ | ||||
| /*    _tx_initialize_high_level         High-level initialization         */ | ||||
| /*    tx_application_define             Application define function       */ | ||||
| /*    _tx_thread_scheduler              ThreadX scheduling loop           */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    main                              Application main program          */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020      William E. Lamie        Initial Version 6.0           */ | ||||
| /*  09-30-2020      Yuxin Zhou              Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*  04-25-2022      Scott Larson            Modified comment(s),          */ | ||||
| /*                                            added EPK initialization,   */ | ||||
| /*                                            resulting in version 6.1.11 */ | ||||
| /*  10-31-2023      Xiuwen Cai              Modified comment(s),          */ | ||||
| /*                                            added random generator      */ | ||||
| /*                                            initialization,             */ | ||||
| /*                                            resulting in version 6.3.0  */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_initialize_kernel_enter(VOID) | ||||
| { | ||||
|  | ||||
|     /* Determine if the compiler has pre-initialized ThreadX.  */ | ||||
|     if (_tx_thread_system_state != TX_INITIALIZE_ALMOST_DONE) | ||||
|     { | ||||
|  | ||||
|         /* No, the initialization still needs to take place.  */ | ||||
|  | ||||
|         /* Ensure that the system state variable is set to indicate | ||||
|            initialization is in progress.  Note that this variable is | ||||
|            later used to represent interrupt nesting.  */ | ||||
|         _tx_thread_system_state =  TX_INITIALIZE_IN_PROGRESS; | ||||
|  | ||||
|         /* Call any port specific preprocessing.  */ | ||||
|         TX_PORT_SPECIFIC_PRE_INITIALIZATION | ||||
|  | ||||
|         /* Invoke the low-level initialization to handle all processor specific | ||||
|            initialization issues.  */ | ||||
|         _tx_initialize_low_level(); | ||||
|  | ||||
|         /* Invoke the high-level initialization to exercise all of the | ||||
|            ThreadX components and the application's initialization | ||||
|            function.  */ | ||||
|         _tx_initialize_high_level(); | ||||
|  | ||||
|         /* Call any port specific post-processing.  */ | ||||
|         TX_PORT_SPECIFIC_POST_INITIALIZATION | ||||
|     } | ||||
|  | ||||
|     /* Optional processing extension.  */ | ||||
|     TX_INITIALIZE_KERNEL_ENTER_EXTENSION | ||||
|  | ||||
|     /* Ensure that the system state variable is set to indicate | ||||
|        initialization is in progress.  Note that this variable is | ||||
|        later used to represent interrupt nesting.  */ | ||||
|     _tx_thread_system_state =  TX_INITIALIZE_IN_PROGRESS; | ||||
|  | ||||
|     /* Optional random number generator initialization.  */ | ||||
|     TX_INITIALIZE_RANDOM_GENERATOR_INITIALIZATION | ||||
|  | ||||
|     /* Call the application provided initialization function.  Pass the | ||||
|        first available memory address to it.  */ | ||||
|     tx_application_define(_tx_initialize_unused_memory); | ||||
|  | ||||
|     /* Set the system state in preparation for entering the thread | ||||
|        scheduler.  */ | ||||
|     _tx_thread_system_state =  TX_INITIALIZE_IS_FINISHED; | ||||
|  | ||||
|     /* Call any port specific pre-scheduler processing.  */ | ||||
|     TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION | ||||
|  | ||||
| #if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) | ||||
|     /* Initialize Execution Profile Kit.  */ | ||||
|     _tx_execution_initialize(); | ||||
| #endif | ||||
|  | ||||
|     /* Enter the scheduling loop to start executing threads!  */ | ||||
|     _tx_thread_schedule(); | ||||
|  | ||||
| #ifdef TX_SAFETY_CRITICAL | ||||
|  | ||||
|     /* If we ever get here, raise safety critical exception.  */ | ||||
|     TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0); | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										102
									
								
								Middlewares/ST/threadx/common/src/tx_initialize_kernel_setup.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								Middlewares/ST/threadx/common/src/tx_initialize_kernel_setup.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Initialize                                                          */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_initialize.h" | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_initialize_kernel_setup                         PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function is called by the compiler's startup code to make      */ | ||||
| /*    ThreadX objects accessible to the compiler's library.  If this      */ | ||||
| /*    function is not called by the compiler, all ThreadX initialization  */ | ||||
| /*    takes place from the kernel enter function defined previously.      */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_initialize_low_level          Low-level initialization          */ | ||||
| /*    _tx_initialize_high_level         High-level initialization         */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    startup code                      Compiler startup code             */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_initialize_kernel_setup(VOID) | ||||
| { | ||||
|  | ||||
|     /* Ensure that the system state variable is set to indicate | ||||
|        initialization is in progress.  Note that this variable is | ||||
|        later used to represent interrupt nesting.  */ | ||||
|     _tx_thread_system_state =  TX_INITIALIZE_IN_PROGRESS; | ||||
|  | ||||
|     /* Call any port specific preprocessing.  */ | ||||
|     TX_PORT_SPECIFIC_PRE_INITIALIZATION | ||||
|  | ||||
|     /* Invoke the low-level initialization to handle all processor specific | ||||
|        initialization issues.  */ | ||||
|     _tx_initialize_low_level(); | ||||
|  | ||||
|     /* Invoke the high-level initialization to exercise all of the | ||||
|        ThreadX components and the application's initialization | ||||
|        function.  */ | ||||
|     _tx_initialize_high_level(); | ||||
|  | ||||
|     /* Call any port specific post-processing.  */ | ||||
|     TX_PORT_SPECIFIC_POST_INITIALIZATION | ||||
|  | ||||
|     /* Set the system state to indicate initialization is almost done.  */ | ||||
|     _tx_thread_system_state =  TX_INITIALIZE_ALMOST_DONE; | ||||
| } | ||||
|  | ||||
							
								
								
									
										317
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_cleanup.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_cleanup.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,317 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Mutex                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_mutex.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_mutex_cleanup                                   PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function processes mutex timeout and thread terminate          */ | ||||
| /*    actions that require the mutex data structures to be cleaned        */ | ||||
| /*    up.                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                        Pointer to suspended thread's     */ | ||||
| /*                                        control block                   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_timeout                Thread timeout processing         */ | ||||
| /*    _tx_thread_terminate              Thread terminate processing       */ | ||||
| /*    _tx_thread_wait_abort             Thread wait abort processing      */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_mutex_cleanup(TX_THREAD  *thread_ptr, ULONG suspension_sequence) | ||||
| { | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
| #endif | ||||
|  | ||||
| TX_MUTEX            *mutex_ptr; | ||||
| UINT                suspended_count; | ||||
| TX_THREAD           *next_thread; | ||||
| TX_THREAD           *previous_thread; | ||||
|  | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|     /* Disable interrupts to remove the suspended thread from the mutex.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Determine if the cleanup is still required.  */ | ||||
|     if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_mutex_cleanup)) | ||||
|     { | ||||
|  | ||||
|         /* Check for valid suspension sequence.  */ | ||||
|         if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence) | ||||
|         { | ||||
|  | ||||
|             /* Setup pointer to mutex control block.  */ | ||||
|             mutex_ptr =  TX_VOID_TO_MUTEX_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); | ||||
|  | ||||
|             /* Check for NULL mutex pointer.  */ | ||||
|             if (mutex_ptr != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Determine if the mutex ID is valid.  */ | ||||
|                 if (mutex_ptr -> tx_mutex_id == TX_MUTEX_ID) | ||||
|                 { | ||||
|  | ||||
|                     /* Determine if there are any thread suspensions.  */ | ||||
|                     if (mutex_ptr -> tx_mutex_suspended_count != TX_NO_SUSPENSIONS) | ||||
|                     { | ||||
| #else | ||||
|  | ||||
|                         /* Setup pointer to mutex control block.  */ | ||||
|                         mutex_ptr =  TX_VOID_TO_MUTEX_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); | ||||
| #endif | ||||
|  | ||||
|                         /* Yes, we still have thread suspension!  */ | ||||
|  | ||||
|                         /* Clear the suspension cleanup flag.  */ | ||||
|                         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|                         /* Decrement the suspension count.  */ | ||||
|                         mutex_ptr -> tx_mutex_suspended_count--; | ||||
|  | ||||
|                         /* Pickup the suspended count.  */ | ||||
|                         suspended_count =  mutex_ptr -> tx_mutex_suspended_count; | ||||
|  | ||||
|                         /* Remove the suspended thread from the list.  */ | ||||
|  | ||||
|                         /* See if this is the only suspended thread on the list.  */ | ||||
|                         if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|                         { | ||||
|  | ||||
|                             /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|                             /* Update the head pointer.  */ | ||||
|                             mutex_ptr -> tx_mutex_suspension_list =  TX_NULL; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* At least one more thread is on the same suspension list.  */ | ||||
|  | ||||
|                             /* Update the links of the adjacent threads.  */ | ||||
|                             next_thread =                                   thread_ptr -> tx_thread_suspended_next; | ||||
|                             previous_thread =                               thread_ptr -> tx_thread_suspended_previous; | ||||
|                             next_thread -> tx_thread_suspended_previous =   previous_thread; | ||||
|                             previous_thread -> tx_thread_suspended_next =   next_thread; | ||||
|  | ||||
|                             /* Determine if we need to update the head pointer.  */ | ||||
|                             if (mutex_ptr -> tx_mutex_suspension_list == thread_ptr) | ||||
|                             { | ||||
|  | ||||
|                                 /* Update the list head pointer.  */ | ||||
|                                 mutex_ptr -> tx_mutex_suspension_list =         next_thread; | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         /* Now we need to determine if this cleanup is from a terminate, timeout, | ||||
|                            or from a wait abort.  */ | ||||
|                         if (thread_ptr -> tx_thread_state == TX_MUTEX_SUSP) | ||||
|                         { | ||||
|  | ||||
|                             /* Timeout condition and the thread still suspended on the mutex. | ||||
|                                Setup return error status and resume the thread.  */ | ||||
|  | ||||
| #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                             /* Increment the total timeouts counter.  */ | ||||
|                             _tx_mutex_performance_timeout_count++; | ||||
|  | ||||
|                             /* Increment the number of timeouts on this semaphore.  */ | ||||
|                             mutex_ptr -> tx_mutex_performance_timeout_count++; | ||||
| #endif | ||||
|  | ||||
|                             /* Setup return status.  */ | ||||
|                             thread_ptr -> tx_thread_suspend_status =  TX_NOT_AVAILABLE; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                             /* Resume the thread!  */ | ||||
|                             _tx_thread_system_ni_resume(thread_ptr); | ||||
| #else | ||||
|  | ||||
|                             /* Temporarily disable preemption.  */ | ||||
|                             _tx_thread_preempt_disable++; | ||||
|  | ||||
|                             /* Restore interrupts.  */ | ||||
|                             TX_RESTORE | ||||
|  | ||||
|                             /* Resume the thread!  */ | ||||
|                             _tx_thread_system_resume(thread_ptr); | ||||
|  | ||||
|                             /* Disable interrupts.  */ | ||||
|                             TX_DISABLE | ||||
| #endif | ||||
|                         } | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_mutex_thread_release                            PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function releases all mutexes owned by the thread. This        */ | ||||
| /*    function is called when the thread completes or is terminated.      */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                        Pointer to thread's control block */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_mutex_put                     Release the mutex                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_shell_entry            Thread completion processing      */ | ||||
| /*    _tx_thread_terminate              Thread terminate processing       */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_mutex_thread_release(TX_THREAD  *thread_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_MUTEX    *mutex_ptr; | ||||
| #ifdef TX_MISRA_ENABLE | ||||
| UINT        status; | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Temporarily disable preemption.  */ | ||||
|     _tx_thread_preempt_disable++; | ||||
|  | ||||
|     /* Loop to look at all the mutexes.  */ | ||||
|     do | ||||
|     { | ||||
|  | ||||
|         /* Pickup the mutex head pointer.  */ | ||||
|         mutex_ptr =  thread_ptr -> tx_thread_owned_mutex_list; | ||||
|  | ||||
|         /* Determine if there is a mutex.  */ | ||||
|         if (mutex_ptr != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Yes, set the ownership count to 1.  */ | ||||
|             mutex_ptr -> tx_mutex_ownership_count =  ((UINT) 1); | ||||
|  | ||||
|             /* Restore interrupts.   */ | ||||
|             TX_RESTORE | ||||
|  | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|             /* Release the mutex.  */ | ||||
|             do | ||||
|             { | ||||
|                 status =  _tx_mutex_put(mutex_ptr); | ||||
|             } while (status != TX_SUCCESS); | ||||
| #else | ||||
|             _tx_mutex_put(mutex_ptr); | ||||
| #endif | ||||
|  | ||||
|             /* Disable interrupts.  */ | ||||
|             TX_DISABLE | ||||
|  | ||||
|             /* Move to the next mutex.  */ | ||||
|             mutex_ptr =  thread_ptr -> tx_thread_owned_mutex_list; | ||||
|         } | ||||
|     } while (mutex_ptr != TX_NULL); | ||||
|  | ||||
|     /* Restore preemption.  */ | ||||
|     _tx_thread_preempt_disable--; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
| } | ||||
|  | ||||
							
								
								
									
										148
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_create.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_create.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Mutex                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_mutex.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_mutex_create                                    PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function creates a mutex with optional priority inheritance as */ | ||||
| /*    specified in this call.                                             */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    mutex_ptr                             Pointer to mutex control block*/ | ||||
| /*    name_ptr                              Pointer to mutex name         */ | ||||
| /*    inherit                               Priority inheritance option   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_MUTEX        *next_mutex; | ||||
| TX_MUTEX        *previous_mutex; | ||||
|  | ||||
|  | ||||
|     /* Initialize mutex control block to all zeros.  */ | ||||
|     TX_MEMSET(mutex_ptr, 0, (sizeof(TX_MUTEX))); | ||||
|  | ||||
|     /* Setup the basic mutex fields.  */ | ||||
|     mutex_ptr -> tx_mutex_name =             name_ptr; | ||||
|     mutex_ptr -> tx_mutex_inherit =          inherit; | ||||
|  | ||||
|     /* Disable interrupts to place the mutex on the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Setup the mutex ID to make it valid.  */ | ||||
|     mutex_ptr -> tx_mutex_id =  TX_MUTEX_ID; | ||||
|  | ||||
|     /* Setup the thread mutex release function pointer.  */ | ||||
|     _tx_thread_mutex_release =  &(_tx_mutex_thread_release); | ||||
|  | ||||
|     /* Place the mutex on the list of created mutexes.  First, | ||||
|        check for an empty list.  */ | ||||
|     if (_tx_mutex_created_count == TX_EMPTY) | ||||
|     { | ||||
|  | ||||
|         /* The created mutex list is empty.  Add mutex to empty list.  */ | ||||
|         _tx_mutex_created_ptr =                   mutex_ptr; | ||||
|         mutex_ptr -> tx_mutex_created_next =      mutex_ptr; | ||||
|         mutex_ptr -> tx_mutex_created_previous =  mutex_ptr; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* This list is not NULL, add to the end of the list.  */ | ||||
|         next_mutex =      _tx_mutex_created_ptr; | ||||
|         previous_mutex =  next_mutex -> tx_mutex_created_previous; | ||||
|  | ||||
|         /* Place the new mutex in the list.  */ | ||||
|         next_mutex -> tx_mutex_created_previous =  mutex_ptr; | ||||
|         previous_mutex -> tx_mutex_created_next =  mutex_ptr; | ||||
|  | ||||
|         /* Setup this mutex's next and previous created links.  */ | ||||
|         mutex_ptr -> tx_mutex_created_previous =  previous_mutex; | ||||
|         mutex_ptr -> tx_mutex_created_next =      next_mutex; | ||||
|     } | ||||
|  | ||||
|     /* Increment the ownership count.  */ | ||||
|     _tx_mutex_created_count++; | ||||
|  | ||||
|     /* Optional mutex create extended processing.  */ | ||||
|     TX_MUTEX_CREATE_EXTENSION(mutex_ptr) | ||||
|  | ||||
|     /* If trace is enabled, register this object.  */ | ||||
|     TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_MUTEX, mutex_ptr, name_ptr, inherit, 0) | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_CREATE, mutex_ptr, inherit, TX_POINTER_TO_ULONG_CONVERT(&next_mutex), 0, TX_TRACE_MUTEX_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_MUTEX_CREATE_INSERT | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										245
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_delete.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_delete.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,245 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Mutex                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_mutex.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_mutex_delete                                    PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function deletes the specified mutex.  All threads             */ | ||||
| /*    suspended on the mutex are resumed with the TX_DELETED status       */ | ||||
| /*    code.                                                               */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    mutex_ptr                         Pointer to mutex control block    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_mutex_put                     Release an owned mutex            */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_mutex_delete(TX_MUTEX *mutex_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *owner_thread; | ||||
| UINT            suspended_count; | ||||
| TX_MUTEX        *next_mutex; | ||||
| TX_MUTEX        *previous_mutex; | ||||
| #ifdef TX_MISRA_ENABLE | ||||
| UINT            status; | ||||
| #endif | ||||
|  | ||||
|     /* Disable interrupts to remove the mutex from the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_DELETE, mutex_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_MUTEX_EVENTS) | ||||
|  | ||||
|     /* Optional mutex delete extended processing.  */ | ||||
|     TX_MUTEX_DELETE_EXTENSION(mutex_ptr) | ||||
|  | ||||
|     /* If trace is enabled, unregister this object.  */ | ||||
|     TX_TRACE_OBJECT_UNREGISTER(mutex_ptr) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_MUTEX_DELETE_INSERT | ||||
|  | ||||
|     /* Clear the mutex ID to make it invalid.  */ | ||||
|     mutex_ptr -> tx_mutex_id =  TX_CLEAR_ID; | ||||
|  | ||||
|     /* Decrement the created count.  */ | ||||
|     _tx_mutex_created_count--; | ||||
|  | ||||
|     /* See if the mutex is the only one on the list.  */ | ||||
|     if (_tx_mutex_created_count == TX_EMPTY) | ||||
|     { | ||||
|  | ||||
|         /* Only created mutex, just set the created list to NULL.  */ | ||||
|         _tx_mutex_created_ptr =  TX_NULL; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Link-up the neighbors.  */ | ||||
|         next_mutex =                               mutex_ptr -> tx_mutex_created_next; | ||||
|         previous_mutex =                           mutex_ptr -> tx_mutex_created_previous; | ||||
|         next_mutex -> tx_mutex_created_previous =  previous_mutex; | ||||
|         previous_mutex -> tx_mutex_created_next =  next_mutex; | ||||
|  | ||||
|         /* See if we have to update the created list head pointer.  */ | ||||
|         if (_tx_mutex_created_ptr == mutex_ptr) | ||||
|         { | ||||
|  | ||||
|             /* Yes, move the head pointer to the next link. */ | ||||
|             _tx_mutex_created_ptr =  next_mutex; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Temporarily disable preemption.  */ | ||||
|     _tx_thread_preempt_disable++; | ||||
|  | ||||
|     /* Pickup the suspension information.  */ | ||||
|     thread_ptr =                             mutex_ptr -> tx_mutex_suspension_list; | ||||
|     mutex_ptr -> tx_mutex_suspension_list =  TX_NULL; | ||||
|     suspended_count =                        mutex_ptr -> tx_mutex_suspended_count; | ||||
|     mutex_ptr -> tx_mutex_suspended_count =  TX_NO_SUSPENSIONS; | ||||
|  | ||||
|  | ||||
|     /* Determine if the mutex is currently on a thread's ownership list.  */ | ||||
|  | ||||
|     /* Setup pointer to owner of mutex.  */ | ||||
|     owner_thread =  mutex_ptr -> tx_mutex_owner; | ||||
|  | ||||
|     /* Determine if there is a valid thread pointer.  */ | ||||
|     if (owner_thread != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Yes, remove this mutex from the owned list.  */ | ||||
|  | ||||
|         /* Set the ownership count to 1.  */ | ||||
|         mutex_ptr -> tx_mutex_ownership_count =  ((UINT) 1); | ||||
|  | ||||
|         /* Restore interrupts.   */ | ||||
|         TX_RESTORE | ||||
|  | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|         /* Release the mutex.  */ | ||||
|         do | ||||
|         { | ||||
|             status =  _tx_mutex_put(mutex_ptr); | ||||
|         } while (status != TX_SUCCESS); | ||||
| #else | ||||
|         _tx_mutex_put(mutex_ptr); | ||||
| #endif | ||||
|  | ||||
|         /* Disable interrupts.  */ | ||||
|         TX_DISABLE | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Walk through the mutex list to resume any and all threads suspended | ||||
|        on this mutex.  */ | ||||
|     while (suspended_count != ((ULONG) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Decrement the suspension count.  */ | ||||
|         suspended_count--; | ||||
|  | ||||
|         /* Lockout interrupts.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* Clear the cleanup pointer, this prevents the timeout from doing | ||||
|            anything.  */ | ||||
|         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|         /* Set the return status in the thread to TX_DELETED.  */ | ||||
|         thread_ptr -> tx_thread_suspend_status =  TX_DELETED; | ||||
|  | ||||
|         /* Move the thread pointer ahead.  */ | ||||
|         next_thread =  thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Resume the thread!  */ | ||||
|         _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #else | ||||
|  | ||||
|         /* Temporarily disable preemption again.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Resume the thread.  */ | ||||
|         _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|         /* Move to next thread.  */ | ||||
|         thread_ptr =  next_thread; | ||||
|     } | ||||
|  | ||||
|     /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h.  */ | ||||
|     TX_MUTEX_DELETE_PORT_COMPLETION(mutex_ptr) | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Release previous preempt disable.  */ | ||||
|     _tx_thread_preempt_disable--; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Check for preemption.  */ | ||||
|     _tx_thread_system_preempt_check(); | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										411
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_get.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										411
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_get.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,411 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Mutex                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_mutex.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_mutex_get                                       PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function gets the specified mutex.  If the calling thread      */ | ||||
| /*    already owns the mutex, an ownership count is simply increased.     */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    mutex_ptr                         Pointer to mutex control block    */ | ||||
| /*    wait_option                       Suspension option                 */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_suspend         Suspend thread service            */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*    _tx_mutex_priority_change         Inherit thread priority           */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_MUTEX        *next_mutex; | ||||
| TX_MUTEX        *previous_mutex; | ||||
| TX_THREAD       *mutex_owner; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| UINT            status; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to get an instance from the mutex.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Increment the total mutex get counter.  */ | ||||
|     _tx_mutex_performance_get_count++; | ||||
|  | ||||
|     /* Increment the number of attempts to get this mutex.  */ | ||||
|     mutex_ptr -> tx_mutex_performance_get_count++; | ||||
| #endif | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_GET, mutex_ptr, wait_option, TX_POINTER_TO_ULONG_CONVERT(mutex_ptr -> tx_mutex_owner), mutex_ptr -> tx_mutex_ownership_count, TX_TRACE_MUTEX_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_MUTEX_GET_INSERT | ||||
|  | ||||
|     /* Pickup thread pointer.  */ | ||||
|     TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
|     /* Determine if this mutex is available.  */ | ||||
|     if (mutex_ptr -> tx_mutex_ownership_count == ((UINT) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Set the ownership count to 1.  */ | ||||
|         mutex_ptr -> tx_mutex_ownership_count =  ((UINT) 1); | ||||
|  | ||||
|         /* Remember that the calling thread owns the mutex.  */ | ||||
|         mutex_ptr -> tx_mutex_owner =  thread_ptr; | ||||
|  | ||||
|         /* Determine if the thread pointer is valid.  */ | ||||
|         if (thread_ptr != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Determine if priority inheritance is required.  */ | ||||
|             if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) | ||||
|             { | ||||
|  | ||||
|                 /* Remember the current priority of thread.  */ | ||||
|                 mutex_ptr -> tx_mutex_original_priority =   thread_ptr -> tx_thread_priority; | ||||
|  | ||||
|                 /* Setup the highest priority waiting thread.  */ | ||||
|                 mutex_ptr -> tx_mutex_highest_priority_waiting =  ((UINT) TX_MAX_PRIORITIES); | ||||
|             } | ||||
|  | ||||
|             /* Pickup next mutex pointer, which is the head of the list.  */ | ||||
|             next_mutex =  thread_ptr -> tx_thread_owned_mutex_list; | ||||
|  | ||||
|             /* Determine if this thread owns any other mutexes that have priority inheritance.  */ | ||||
|             if (next_mutex != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Non-empty list. Link up the mutex.  */ | ||||
|  | ||||
|                 /* Pickup the next and previous mutex pointer.  */ | ||||
|                 previous_mutex =  next_mutex -> tx_mutex_owned_previous; | ||||
|  | ||||
|                 /* Place the owned mutex in the list.  */ | ||||
|                 next_mutex -> tx_mutex_owned_previous =  mutex_ptr; | ||||
|                 previous_mutex -> tx_mutex_owned_next =  mutex_ptr; | ||||
|  | ||||
|                 /* Setup this mutex's next and previous created links.  */ | ||||
|                 mutex_ptr -> tx_mutex_owned_previous =  previous_mutex; | ||||
|                 mutex_ptr -> tx_mutex_owned_next =      next_mutex; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* The owned mutex list is empty.  Add mutex to empty list.  */ | ||||
|                 thread_ptr -> tx_thread_owned_mutex_list =     mutex_ptr; | ||||
|                 mutex_ptr -> tx_mutex_owned_next =             mutex_ptr; | ||||
|                 mutex_ptr -> tx_mutex_owned_previous =         mutex_ptr; | ||||
|             } | ||||
|  | ||||
|             /* Increment the number of mutexes owned counter.  */ | ||||
|             thread_ptr -> tx_thread_owned_mutex_count++; | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Return success.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|     } | ||||
|  | ||||
|     /* Otherwise, see if the owning thread is trying to obtain the same mutex.  */ | ||||
|     else if (mutex_ptr -> tx_mutex_owner == thread_ptr) | ||||
|     { | ||||
|  | ||||
|         /* The owning thread is requesting the mutex again, just | ||||
|            increment the ownership count.  */ | ||||
|         mutex_ptr -> tx_mutex_ownership_count++; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Return success.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Determine if the request specifies suspension.  */ | ||||
|         if (wait_option != TX_NO_WAIT) | ||||
|         { | ||||
|  | ||||
|             /* Determine if the preempt disable flag is non-zero.  */ | ||||
|             if (_tx_thread_preempt_disable != ((UINT) 0)) | ||||
|             { | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion.  */ | ||||
|                 status =  TX_NOT_AVAILABLE; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Prepare for suspension of this thread.  */ | ||||
|  | ||||
|                 /* Pickup the mutex owner.  */ | ||||
|                 mutex_owner =  mutex_ptr -> tx_mutex_owner; | ||||
|  | ||||
| #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                 /* Increment the total mutex suspension counter.  */ | ||||
|                 _tx_mutex_performance_suspension_count++; | ||||
|  | ||||
|                 /* Increment the number of suspensions on this mutex.  */ | ||||
|                 mutex_ptr -> tx_mutex_performance_suspension_count++; | ||||
|  | ||||
|                 /* Determine if a priority inversion is present.  */ | ||||
|                 if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_priority) | ||||
|                 { | ||||
|  | ||||
|                     /* Yes, priority inversion is present!  */ | ||||
|  | ||||
|                     /* Increment the total mutex priority inversions counter.  */ | ||||
|                     _tx_mutex_performance_priority_inversion_count++; | ||||
|  | ||||
|                     /* Increment the number of priority inversions on this mutex.  */ | ||||
|                     mutex_ptr -> tx_mutex_performance_priority_inversion_count++; | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                     /* Increment the number of total thread priority inversions.  */ | ||||
|                     _tx_thread_performance_priority_inversion_count++; | ||||
|  | ||||
|                     /* Increment the number of priority inversions for this thread.  */ | ||||
|                     thread_ptr -> tx_thread_performance_priority_inversion_count++; | ||||
| #endif | ||||
|                 } | ||||
| #endif | ||||
|  | ||||
|                 /* Setup cleanup routine pointer.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_cleanup =  &(_tx_mutex_cleanup); | ||||
|  | ||||
|                 /* Setup cleanup information, i.e. this mutex control | ||||
|                    block.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_control_block =  (VOID *) mutex_ptr; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                 /* Increment the suspension sequence number, which is used to identify | ||||
|                    this suspension event.  */ | ||||
|                 thread_ptr -> tx_thread_suspension_sequence++; | ||||
| #endif | ||||
|  | ||||
|                 /* Setup suspension list.  */ | ||||
|                 if (mutex_ptr -> tx_mutex_suspended_count == TX_NO_SUSPENSIONS) | ||||
|                 { | ||||
|  | ||||
|                     /* No other threads are suspended.  Setup the head pointer and | ||||
|                        just setup this threads pointers to itself.  */ | ||||
|                     mutex_ptr -> tx_mutex_suspension_list =         thread_ptr; | ||||
|                     thread_ptr -> tx_thread_suspended_next =        thread_ptr; | ||||
|                     thread_ptr -> tx_thread_suspended_previous =    thread_ptr; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* This list is not NULL, add current thread to the end. */ | ||||
|                     next_thread =                                   mutex_ptr -> tx_mutex_suspension_list; | ||||
|                     thread_ptr -> tx_thread_suspended_next =        next_thread; | ||||
|                     previous_thread =                               next_thread -> tx_thread_suspended_previous; | ||||
|                     thread_ptr -> tx_thread_suspended_previous =    previous_thread; | ||||
|                     previous_thread -> tx_thread_suspended_next =   thread_ptr; | ||||
|                     next_thread -> tx_thread_suspended_previous =   thread_ptr; | ||||
|                 } | ||||
|  | ||||
|                 /* Increment the suspension count.  */ | ||||
|                 mutex_ptr -> tx_mutex_suspended_count++; | ||||
|  | ||||
|                 /* Set the state to suspended.  */ | ||||
|                 thread_ptr -> tx_thread_state =    TX_MUTEX_SUSP; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                 /* Determine if we need to raise the priority of the thread | ||||
|                    owning the mutex.  */ | ||||
|                 if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) | ||||
|                 { | ||||
|  | ||||
|                     /* Determine if this is the highest priority to raise for this mutex.  */ | ||||
|                     if (mutex_ptr -> tx_mutex_highest_priority_waiting > thread_ptr -> tx_thread_priority) | ||||
|                     { | ||||
|  | ||||
|                         /* Remember this priority.  */ | ||||
|                         mutex_ptr -> tx_mutex_highest_priority_waiting =  thread_ptr -> tx_thread_priority; | ||||
|                     } | ||||
|  | ||||
|                     /* Determine if we have to update inherit priority level of the mutex owner.  */ | ||||
|                     if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_inherit_priority) | ||||
|                     { | ||||
|  | ||||
|                         /* Remember the new priority inheritance priority.  */ | ||||
|                         mutex_owner -> tx_thread_inherit_priority =  thread_ptr -> tx_thread_priority; | ||||
|                     } | ||||
|  | ||||
|                     /* Priority inheritance is requested, check to see if the thread that owns the mutex is lower priority.  */ | ||||
|                     if (mutex_owner -> tx_thread_priority > thread_ptr -> tx_thread_priority) | ||||
|                     { | ||||
|  | ||||
|                         /* Yes, raise the suspended, owning thread's priority to that | ||||
|                            of the current thread.  */ | ||||
|                         _tx_mutex_priority_change(mutex_owner, thread_ptr -> tx_thread_priority); | ||||
|  | ||||
| #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                         /* Increment the total mutex priority inheritance counter.  */ | ||||
|                         _tx_mutex_performance__priority_inheritance_count++; | ||||
|  | ||||
|                         /* Increment the number of priority inheritance situations on this mutex.  */ | ||||
|                         mutex_ptr -> tx_mutex_performance__priority_inheritance_count++; | ||||
| #endif | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 /* Call actual non-interruptable thread suspension routine.  */ | ||||
|                 _tx_thread_system_ni_suspend(thread_ptr, wait_option); | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
| #else | ||||
|  | ||||
|                 /* Set the suspending flag.  */ | ||||
|                 thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|                 /* Setup the timeout period.  */ | ||||
|                 thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  wait_option; | ||||
|  | ||||
|                 /* Temporarily disable preemption.  */ | ||||
|                 _tx_thread_preempt_disable++; | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Determine if we need to raise the priority of the thread | ||||
|                    owning the mutex.  */ | ||||
|                 if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) | ||||
|                 { | ||||
|  | ||||
|                     /* Determine if this is the highest priority to raise for this mutex.  */ | ||||
|                     if (mutex_ptr -> tx_mutex_highest_priority_waiting > thread_ptr -> tx_thread_priority) | ||||
|                     { | ||||
|  | ||||
|                         /* Remember this priority.  */ | ||||
|                         mutex_ptr -> tx_mutex_highest_priority_waiting =  thread_ptr -> tx_thread_priority; | ||||
|                     } | ||||
|  | ||||
|                     /* Determine if we have to update inherit priority level of the mutex owner.  */ | ||||
|                     if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_inherit_priority) | ||||
|                     { | ||||
|  | ||||
|                         /* Remember the new priority inheritance priority.  */ | ||||
|                         mutex_owner -> tx_thread_inherit_priority =  thread_ptr -> tx_thread_priority; | ||||
|                     } | ||||
|  | ||||
|                     /* Priority inheritance is requested, check to see if the thread that owns the mutex is lower priority.  */ | ||||
|                     if (mutex_owner -> tx_thread_priority > thread_ptr -> tx_thread_priority) | ||||
|                     { | ||||
|  | ||||
|                         /* Yes, raise the suspended, owning thread's priority to that | ||||
|                            of the current thread.  */ | ||||
|                         _tx_mutex_priority_change(mutex_owner, thread_ptr -> tx_thread_priority); | ||||
|  | ||||
| #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                         /* Increment the total mutex priority inheritance counter.  */ | ||||
|                         _tx_mutex_performance__priority_inheritance_count++; | ||||
|  | ||||
|                         /* Increment the number of priority inheritance situations on this mutex.  */ | ||||
|                         mutex_ptr -> tx_mutex_performance__priority_inheritance_count++; | ||||
| #endif | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 /* Call actual thread suspension routine.  */ | ||||
|                 _tx_thread_system_suspend(thread_ptr); | ||||
| #endif | ||||
|                 /* Return the completion status.  */ | ||||
|                 status =  thread_ptr -> tx_thread_suspend_status; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Immediate return, return error completion.  */ | ||||
|             status =  TX_NOT_AVAILABLE; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										149
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_info_get.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_info_get.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,149 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Mutex                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_mutex.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_mutex_info_get                                  PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function retrieves information from the specified mutex.       */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    mutex_ptr                         Pointer to mutex control block    */ | ||||
| /*    name                              Destination for the mutex name    */ | ||||
| /*    count                             Destination for the owner count   */ | ||||
| /*    owner                             Destination for the owner's       */ | ||||
| /*                                        thread control block pointer    */ | ||||
| /*    first_suspended                   Destination for pointer of first  */ | ||||
| /*                                        thread suspended on the mutex   */ | ||||
| /*    suspended_count                   Destination for suspended count   */ | ||||
| /*    next_mutex                        Destination for pointer to next   */ | ||||
| /*                                        mutex on the created list       */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner, | ||||
|                     TX_THREAD **first_suspended, ULONG *suspended_count, | ||||
|                     TX_MUTEX **next_mutex) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_INFO_GET, mutex_ptr, 0, 0, 0, TX_TRACE_MUTEX_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_MUTEX_INFO_GET_INSERT | ||||
|  | ||||
|     /* Retrieve all the pertinent information and return it in the supplied | ||||
|        destinations.  */ | ||||
|  | ||||
|     /* Retrieve the name of the mutex.  */ | ||||
|     if (name != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *name =  mutex_ptr -> tx_mutex_name; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the current ownership count of the mutex.  */ | ||||
|     if (count != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *count =  ((ULONG) mutex_ptr -> tx_mutex_ownership_count); | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the current owner of the mutex.  */ | ||||
|     if (owner != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *owner =  mutex_ptr -> tx_mutex_owner; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the first thread suspended on this mutex.  */ | ||||
|     if (first_suspended != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *first_suspended =  mutex_ptr -> tx_mutex_suspension_list; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the number of threads suspended on this mutex.  */ | ||||
|     if (suspended_count != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *suspended_count =  (ULONG) mutex_ptr -> tx_mutex_suspended_count; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the pointer to the next mutex created.  */ | ||||
|     if (next_mutex != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *next_mutex =  mutex_ptr -> tx_mutex_created_next; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										145
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_initialize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_initialize.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Mutex                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_mutex.h" | ||||
|  | ||||
|  | ||||
| #ifndef TX_INLINE_INITIALIZATION | ||||
|  | ||||
| /* Locate mutex component data in this file.  */ | ||||
|  | ||||
| /* Define the head pointer of the created mutex list.  */ | ||||
|  | ||||
| TX_MUTEX *   _tx_mutex_created_ptr; | ||||
|  | ||||
|  | ||||
| /* Define the variable that holds the number of created mutexes. */ | ||||
|  | ||||
| ULONG        _tx_mutex_created_count; | ||||
|  | ||||
|  | ||||
| #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
| /* Define the total number of mutex puts.  */ | ||||
|  | ||||
| ULONG        _tx_mutex_performance_put_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of mutex gets.  */ | ||||
|  | ||||
| ULONG        _tx_mutex_performance_get_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of mutex suspensions.  */ | ||||
|  | ||||
| ULONG        _tx_mutex_performance_suspension_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of mutex timeouts.  */ | ||||
|  | ||||
| ULONG        _tx_mutex_performance_timeout_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of priority inversions.  */ | ||||
|  | ||||
| ULONG        _tx_mutex_performance_priority_inversion_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of priority inheritance conditions.  */ | ||||
|  | ||||
| ULONG        _tx_mutex_performance__priority_inheritance_count; | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_mutex_initialize                                PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function initializes the various control data structures for   */ | ||||
| /*    the mutex component.                                                */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_initialize_high_level         High level initialization         */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            opt out of function when    */ | ||||
| /*                                            TX_INLINE_INITIALIZATION is */ | ||||
| /*                                            defined,                    */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_mutex_initialize(VOID) | ||||
| { | ||||
|  | ||||
| #ifndef TX_DISABLE_REDUNDANT_CLEARING | ||||
|  | ||||
|     /* Initialize the head pointer of the created mutexes list and the | ||||
|        number of mutexes created.  */ | ||||
|     _tx_mutex_created_ptr =        TX_NULL; | ||||
|     _tx_mutex_created_count =      TX_EMPTY; | ||||
|  | ||||
| #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Initialize the mutex performance counters.  */ | ||||
|     _tx_mutex_performance_put_count =                   ((ULONG) 0); | ||||
|     _tx_mutex_performance_get_count =                   ((ULONG) 0); | ||||
|     _tx_mutex_performance_suspension_count =            ((ULONG) 0); | ||||
|     _tx_mutex_performance_timeout_count =               ((ULONG) 0); | ||||
|     _tx_mutex_performance_priority_inversion_count =    ((ULONG) 0); | ||||
|     _tx_mutex_performance__priority_inheritance_count =  ((ULONG) 0); | ||||
| #endif | ||||
| #endif | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										267
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_prioritize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										267
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_prioritize.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,267 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Mutex                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_mutex.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_mutex_prioritize                                PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function places the highest priority suspended thread at the   */ | ||||
| /*    front of the suspension list.  All other threads remain in the same */ | ||||
| /*    FIFO suspension order.                                              */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    mutex_ptr                         Pointer to mutex control block    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_mutex_prioritize(TX_MUTEX *mutex_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_THREAD       *priority_thread_ptr; | ||||
| TX_THREAD       *head_ptr; | ||||
| UINT            suspended_count; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| UINT            list_changed; | ||||
| #ifdef TX_MISRA_ENABLE | ||||
| UINT            status; | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PRIORITIZE, mutex_ptr, mutex_ptr -> tx_mutex_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_MUTEX_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_MUTEX_PRIORITIZE_INSERT | ||||
|  | ||||
|     /* Pickup the suspended count.  */ | ||||
|     suspended_count =  mutex_ptr -> tx_mutex_suspended_count; | ||||
|  | ||||
|     /* Determine if there are fewer than 2 suspended threads.  */ | ||||
|     if (suspended_count < ((UINT) 2)) | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|  | ||||
|     /* Determine if there how many threads are suspended on this mutex.  */ | ||||
|     else if (suspended_count == ((UINT) 2)) | ||||
|     { | ||||
|  | ||||
|         /* Pickup the head pointer and the next pointer.  */ | ||||
|         head_ptr =  mutex_ptr -> tx_mutex_suspension_list; | ||||
|         next_thread =  head_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|         /* Determine if the next suspended thread has a higher priority.  */ | ||||
|         if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority)) | ||||
|         { | ||||
|  | ||||
|             /* Yes, move the list head to the next thread.  */ | ||||
|             mutex_ptr -> tx_mutex_suspension_list =  next_thread; | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Remember the suspension count and head pointer.  */ | ||||
|         head_ptr =   mutex_ptr -> tx_mutex_suspension_list; | ||||
|  | ||||
|         /* Default the highest priority thread to the thread at the front of the list.  */ | ||||
|         priority_thread_ptr =  head_ptr; | ||||
|  | ||||
|         /* Setup search pointer.  */ | ||||
|         thread_ptr =  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|         /* Disable preemption.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Set the list changed flag to false.  */ | ||||
|         list_changed =  TX_FALSE; | ||||
|  | ||||
|         /* Search through the list to find the highest priority thread.  */ | ||||
|         do | ||||
|         { | ||||
|  | ||||
|             /* Is the current thread higher priority?  */ | ||||
|             if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, remember that this thread is the highest priority.  */ | ||||
|                 priority_thread_ptr =  thread_ptr; | ||||
|             } | ||||
|  | ||||
|             /* Restore interrupts temporarily.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Disable interrupts again.  */ | ||||
|             TX_DISABLE | ||||
|  | ||||
|             /* Determine if any changes to the list have occurred while | ||||
|                interrupts were enabled.  */ | ||||
|  | ||||
|             /* Is the list head the same?  */ | ||||
|             if (head_ptr != mutex_ptr -> tx_mutex_suspension_list) | ||||
|             { | ||||
|  | ||||
|                 /* The list head has changed, set the list changed flag.  */ | ||||
|                 list_changed =  TX_TRUE; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Is the suspended count the same?  */ | ||||
|                 if (suspended_count != mutex_ptr -> tx_mutex_suspended_count) | ||||
|                 { | ||||
|  | ||||
|                     /* The list head has changed, set the list changed flag.  */ | ||||
|                     list_changed =  TX_TRUE; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             /* Determine if the list has changed.  */ | ||||
|             if (list_changed == TX_FALSE) | ||||
|             { | ||||
|  | ||||
|                 /* Move the thread pointer to the next thread.  */ | ||||
|                 thread_ptr =  thread_ptr -> tx_thread_suspended_next; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Remember the suspension count and head pointer.  */ | ||||
|                 head_ptr =   mutex_ptr -> tx_mutex_suspension_list; | ||||
|                 suspended_count =  mutex_ptr -> tx_mutex_suspended_count; | ||||
|  | ||||
|                 /* Default the highest priority thread to the thread at the front of the list.  */ | ||||
|                 priority_thread_ptr =  head_ptr; | ||||
|  | ||||
|                 /* Setup search pointer.  */ | ||||
|                 thread_ptr =  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|                 /* Reset the list changed flag.  */ | ||||
|                 list_changed =  TX_FALSE; | ||||
|             } | ||||
|  | ||||
|         } while (thread_ptr != head_ptr); | ||||
|  | ||||
|         /* Release preemption.  */ | ||||
|         _tx_thread_preempt_disable--; | ||||
|  | ||||
|         /* Now determine if the highest priority thread is at the front | ||||
|            of the list.  */ | ||||
|         if (priority_thread_ptr != head_ptr) | ||||
|         { | ||||
|  | ||||
|             /* No, we need to move the highest priority suspended thread to the | ||||
|                front of the list.  */ | ||||
|  | ||||
|             /* First, remove the highest priority thread by updating the | ||||
|                adjacent suspended threads.  */ | ||||
|             next_thread =                                  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|             previous_thread =                              priority_thread_ptr -> tx_thread_suspended_previous; | ||||
|             next_thread -> tx_thread_suspended_previous =  previous_thread; | ||||
|             previous_thread -> tx_thread_suspended_next =  next_thread; | ||||
|  | ||||
|             /* Now, link the highest priority thread at the front of the list.  */ | ||||
|             previous_thread =                                      head_ptr -> tx_thread_suspended_previous; | ||||
|             priority_thread_ptr -> tx_thread_suspended_next =      head_ptr; | ||||
|             priority_thread_ptr -> tx_thread_suspended_previous =  previous_thread; | ||||
|             previous_thread -> tx_thread_suspended_next =          priority_thread_ptr; | ||||
|             head_ptr -> tx_thread_suspended_previous =             priority_thread_ptr; | ||||
|  | ||||
|             /* Move the list head pointer to the highest priority suspended thread.  */ | ||||
|             mutex_ptr -> tx_mutex_suspension_list =  priority_thread_ptr; | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Check for preemption.  */ | ||||
|         _tx_thread_system_preempt_check(); | ||||
|     } | ||||
|  | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|  | ||||
|     /* Initialize status to success.  */ | ||||
|     status =  TX_SUCCESS; | ||||
|  | ||||
|     /* Define extended processing option.  */ | ||||
|     status =  TX_MUTEX_PRIORITIZE_MISRA_EXTENSION(status); | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| #else | ||||
|  | ||||
|     /* Return successful completion.  */ | ||||
|     return(TX_SUCCESS); | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										339
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_priority_change.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										339
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_priority_change.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,339 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Mutex                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_mutex.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_mutex_priority_change                           PORTABLE C      */ | ||||
| /*                                                           6.1.6        */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function changes the priority of the specified thread for the  */ | ||||
| /*    priority inheritance option of the mutex service.                   */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                            Pointer to thread to suspend  */ | ||||
| /*    new_priority                          New thread priority           */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread                     */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*    _tx_thread_system_suspend         Suspend thread                    */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_mutex_get                     Inherit priority                  */ | ||||
| /*    _tx_mutex_put                     Restore previous priority         */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020      William E. Lamie        Initial Version 6.0           */ | ||||
| /*  09-30-2020      William E. Lamie        Modified comment(s), and      */ | ||||
| /*                                            change thread state from    */ | ||||
| /*                                            TX_SUSPENDED to             */ | ||||
| /*                                            TX_PRIORITY_CHANGE before   */ | ||||
| /*                                            calling                     */ | ||||
| /*                                            _tx_thread_system_suspend,  */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*  04-02-2021      Scott Larson            Modified comments, fixed      */ | ||||
| /*                                            mapping current thread's    */ | ||||
| /*                                            priority rather than next,  */ | ||||
| /*                                            resulting in version 6.1.6  */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_mutex_priority_change(TX_THREAD *thread_ptr, UINT new_priority) | ||||
| { | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
| #endif | ||||
|  | ||||
| TX_THREAD       *execute_ptr; | ||||
| TX_THREAD       *next_execute_ptr; | ||||
| UINT            original_priority; | ||||
| #ifndef TX_DISABLE_PREEMPTION_THRESHOLD | ||||
| ULONG           priority_bit; | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
| UINT            map_index; | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
|  | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|     /* Lockout interrupts while the thread is being suspended.  */ | ||||
|     TX_DISABLE | ||||
| #endif | ||||
|  | ||||
|     /* Determine if this thread is currently ready.  */ | ||||
|     if (thread_ptr -> tx_thread_state != TX_READY) | ||||
|     { | ||||
|  | ||||
|         /* Change thread priority to the new mutex priority-inheritance priority.  */ | ||||
|         thread_ptr -> tx_thread_priority =  new_priority; | ||||
|  | ||||
|         /* Determine how to setup the thread's preemption-threshold.  */ | ||||
|         if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority) | ||||
|         { | ||||
|  | ||||
|             /* Change thread preemption-threshold to the user's preemption-threshold.  */ | ||||
|             thread_ptr -> tx_thread_preempt_threshold =  thread_ptr -> tx_thread_user_preempt_threshold; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Change the thread preemption-threshold to the new threshold.  */ | ||||
|             thread_ptr -> tx_thread_preempt_threshold =  new_priority; | ||||
|         } | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #endif | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Pickup the next thread to execute.  */ | ||||
|         execute_ptr =  _tx_thread_execute_ptr; | ||||
|  | ||||
|         /* Save the original priority.  */ | ||||
|         original_priority =  thread_ptr -> tx_thread_priority; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Increment the preempt disable flag.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Set the state to priority change.  */ | ||||
|         thread_ptr -> tx_thread_state =    TX_PRIORITY_CHANGE; | ||||
|  | ||||
|         /* Call actual non-interruptable thread suspension routine.  */ | ||||
|         _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0)); | ||||
|  | ||||
|         /* At this point, the preempt disable flag is still set, so we still have | ||||
|            protection against all preemption.  */ | ||||
|  | ||||
|         /* Change thread priority to the new mutex priority-inheritance priority.  */ | ||||
|         thread_ptr -> tx_thread_priority =  new_priority; | ||||
|  | ||||
|         /* Determine how to setup the thread's preemption-threshold.  */ | ||||
|         if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority) | ||||
|         { | ||||
|  | ||||
|             /* Change thread preemption-threshold to the user's preemption-threshold.  */ | ||||
|             thread_ptr -> tx_thread_preempt_threshold =  thread_ptr -> tx_thread_user_preempt_threshold; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Change the thread preemption-threshold to the new threshold.  */ | ||||
|             thread_ptr -> tx_thread_preempt_threshold =  new_priority; | ||||
|         } | ||||
|  | ||||
|         /* Resume the thread with the new priority.  */ | ||||
|         _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|         /* Decrement the preempt disable flag.  */ | ||||
|         _tx_thread_preempt_disable--; | ||||
| #else | ||||
|  | ||||
|         /* Increment the preempt disable flag.  */ | ||||
|         _tx_thread_preempt_disable =  _tx_thread_preempt_disable + ((UINT) 2); | ||||
|  | ||||
|         /* Set the state to priority change.  */ | ||||
|         thread_ptr -> tx_thread_state =    TX_PRIORITY_CHANGE; | ||||
|  | ||||
|         /* Set the suspending flag. */ | ||||
|         thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|         /* Setup the timeout period.  */ | ||||
|         thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  ((ULONG) 0); | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* The thread is ready and must first be removed from the list.  Call the | ||||
|            system suspend function to accomplish this.  */ | ||||
|         _tx_thread_system_suspend(thread_ptr); | ||||
|  | ||||
|         /* Disable interrupts.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* At this point, the preempt disable flag is still set, so we still have | ||||
|            protection against all preemption.  */ | ||||
|  | ||||
|         /* Change thread priority to the new mutex priority-inheritance priority.  */ | ||||
|         thread_ptr -> tx_thread_priority =  new_priority; | ||||
|  | ||||
|         /* Determine how to setup the thread's preemption-threshold.  */ | ||||
|         if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority) | ||||
|         { | ||||
|  | ||||
|             /* Change thread preemption-threshold to the user's preemption-threshold.  */ | ||||
|             thread_ptr -> tx_thread_preempt_threshold =  thread_ptr -> tx_thread_user_preempt_threshold; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Change the thread preemption-threshold to the new threshold.  */ | ||||
|             thread_ptr -> tx_thread_preempt_threshold =  new_priority; | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Resume the thread with the new priority.  */ | ||||
|         _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|         /* Optional processing extension.  */ | ||||
|         TX_MUTEX_PRIORITY_CHANGE_EXTENSION | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Disable interrupts.  */ | ||||
|         TX_DISABLE | ||||
| #endif | ||||
|  | ||||
|         /* Pickup the next thread to execute.  */ | ||||
|         next_execute_ptr =  _tx_thread_execute_ptr; | ||||
|  | ||||
|         /* Determine if this thread is not the next thread to execute.  */ | ||||
|         if (thread_ptr != next_execute_ptr) | ||||
|         { | ||||
|  | ||||
|             /* Make sure the thread is still ready.  */ | ||||
|             if (thread_ptr -> tx_thread_state == TX_READY) | ||||
|             { | ||||
|  | ||||
|                 /* Now check and see if this thread has an equal or higher priority.  */ | ||||
|                 if (thread_ptr -> tx_thread_priority <= next_execute_ptr -> tx_thread_priority) | ||||
|                 { | ||||
|  | ||||
|                     /* Now determine if this thread was the previously executing thread.  */ | ||||
|                     if (thread_ptr == execute_ptr) | ||||
|                     { | ||||
|  | ||||
|                         /* Yes, this thread was previously executing before we temporarily suspended and resumed | ||||
|                            it in order to change the priority. A lower or same priority thread cannot be the next thread | ||||
|                            to execute in this case since this thread really didn't suspend.  Simply reset the execute | ||||
|                            pointer to this thread.  */ | ||||
|                         _tx_thread_execute_ptr =  thread_ptr; | ||||
|  | ||||
|                         /* Determine if we moved to a lower priority. If so, move the thread to the front of its priority list.  */ | ||||
|                         if (original_priority < new_priority) | ||||
|                         { | ||||
|  | ||||
|                             /* Ensure that this thread is placed at the front of the priority list.  */ | ||||
|                             _tx_thread_priority_list[thread_ptr -> tx_thread_priority] =  thread_ptr; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* Now determine if this thread's preemption-threshold needs to be enforced.  */ | ||||
|                     if (thread_ptr -> tx_thread_preempt_threshold < thread_ptr -> tx_thread_priority) | ||||
|                     { | ||||
|  | ||||
|                         /* Yes, preemption-threshold is in force for this thread. */ | ||||
|  | ||||
|                         /* Compare the next thread to execute thread's priority against the thread's preemption-threshold.  */ | ||||
|                         if (thread_ptr -> tx_thread_preempt_threshold <= next_execute_ptr -> tx_thread_priority) | ||||
|                         { | ||||
|  | ||||
|                             /* We must swap execute pointers to enforce the preemption-threshold of a thread coming out of | ||||
|                                priority inheritance.  */ | ||||
|                             _tx_thread_execute_ptr =  thread_ptr; | ||||
|  | ||||
|                             /* Determine if we moved to a lower priority. If so, move the thread to the front of its priority list.  */ | ||||
|                             if (original_priority < new_priority) | ||||
|                             { | ||||
|  | ||||
|                                 /* Ensure that this thread is placed at the front of the priority list.  */ | ||||
|                                 _tx_thread_priority_list[thread_ptr -> tx_thread_priority] =  thread_ptr; | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
| #ifndef TX_DISABLE_PREEMPTION_THRESHOLD | ||||
|  | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* In this case, we need to mark the preempted map to indicate a thread executed above the | ||||
|                                preemption-threshold.  */ | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|  | ||||
|                             /* Calculate the index into the bit map array.  */ | ||||
|                             map_index =  (thread_ptr -> tx_thread_priority)/ ((UINT) 32); | ||||
|  | ||||
|                             /* Set the active bit to remember that the preempt map has something set.  */ | ||||
|                             TX_DIV32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit) | ||||
|                             _tx_thread_preempted_map_active =  _tx_thread_preempted_map_active | priority_bit; | ||||
| #endif | ||||
|  | ||||
|                             /* Remember that this thread was preempted by a thread above the thread's threshold.  */ | ||||
|                             TX_MOD32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit) | ||||
|                             _tx_thread_preempted_maps[MAP_INDEX] =  _tx_thread_preempted_maps[MAP_INDEX] | priority_bit; | ||||
|                         } | ||||
| #endif | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #endif | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										656
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_put.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										656
									
								
								Middlewares/ST/threadx/common/src/tx_mutex_put.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,656 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Mutex                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_mutex.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_mutex_put                                       PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function puts back an instance of the specified mutex.         */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    mutex_ptr                         Pointer to mutex control block    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Success completion status         */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*    _tx_mutex_priority_change         Restore previous thread priority  */ | ||||
| /*    _tx_mutex_prioritize              Prioritize the mutex suspension   */ | ||||
| /*    _tx_mutex_thread_release          Release all thread's mutexes      */ | ||||
| /*    _tx_mutex_delete                  Release ownership upon mutex      */ | ||||
| /*                                        deletion                        */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_mutex_put(TX_MUTEX *mutex_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_THREAD       *old_owner; | ||||
| UINT            old_priority; | ||||
| UINT            status; | ||||
| TX_MUTEX        *next_mutex; | ||||
| TX_MUTEX        *previous_mutex; | ||||
| UINT            owned_count; | ||||
| UINT            suspended_count; | ||||
| TX_THREAD       *current_thread; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| TX_THREAD       *suspended_thread; | ||||
| UINT            inheritance_priority; | ||||
|  | ||||
|  | ||||
|     /* Setup status to indicate the processing is not complete.  */ | ||||
|     status =  TX_NOT_DONE; | ||||
|  | ||||
|     /* Disable interrupts to put an instance back to the mutex.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Increment the total mutex put counter.  */ | ||||
|     _tx_mutex_performance_put_count++; | ||||
|  | ||||
|     /* Increment the number of attempts to put this mutex.  */ | ||||
|     mutex_ptr -> tx_mutex_performance_put_count++; | ||||
| #endif | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PUT, mutex_ptr, TX_POINTER_TO_ULONG_CONVERT(mutex_ptr -> tx_mutex_owner), mutex_ptr -> tx_mutex_ownership_count, TX_POINTER_TO_ULONG_CONVERT(&old_priority), TX_TRACE_MUTEX_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_MUTEX_PUT_INSERT | ||||
|  | ||||
|     /* Determine if this mutex is owned.  */ | ||||
|     if (mutex_ptr -> tx_mutex_ownership_count != ((UINT) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Pickup the owning thread pointer.  */ | ||||
|         thread_ptr =  mutex_ptr -> tx_mutex_owner; | ||||
|  | ||||
|         /* Pickup thread pointer.  */ | ||||
|         TX_THREAD_GET_CURRENT(current_thread) | ||||
|  | ||||
|         /* Check to see if the mutex is owned by the calling thread.  */ | ||||
|         if (mutex_ptr -> tx_mutex_owner != current_thread) | ||||
|         { | ||||
|  | ||||
|             /* Determine if the preempt disable flag is set, indicating that | ||||
|                the caller is not the application but from ThreadX. In such | ||||
|                cases, the thread mutex owner does not need to match.  */ | ||||
|             if (_tx_thread_preempt_disable == ((UINT) 0)) | ||||
|             { | ||||
|  | ||||
|                 /* Invalid mutex release.  */ | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Caller does not own the mutex.  */ | ||||
|                 status =  TX_NOT_OWNED; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Determine if we should continue.  */ | ||||
|         if (status == TX_NOT_DONE) | ||||
|         { | ||||
|  | ||||
|             /* Decrement the mutex ownership count.  */ | ||||
|             mutex_ptr -> tx_mutex_ownership_count--; | ||||
|  | ||||
|             /* Determine if the mutex is still owned by the current thread.  */ | ||||
|             if (mutex_ptr -> tx_mutex_ownership_count != ((UINT) 0)) | ||||
|             { | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Mutex is still owned, just return successful status.  */ | ||||
|                 status =  TX_SUCCESS; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Check for a NULL thread pointer, which can only happen during initialization.   */ | ||||
|                 if (thread_ptr == TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     /* Restore interrupts.  */ | ||||
|                     TX_RESTORE | ||||
|  | ||||
|                     /* Mutex is now available, return successful status.  */ | ||||
|                     status =  TX_SUCCESS; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* The mutex is now available.   */ | ||||
|  | ||||
|                     /* Remove this mutex from the owned mutex list.  */ | ||||
|  | ||||
|                     /* Decrement the ownership count.  */ | ||||
|                     thread_ptr -> tx_thread_owned_mutex_count--; | ||||
|  | ||||
|                     /* Determine if this mutex was the only one on the list.  */ | ||||
|                     if (thread_ptr -> tx_thread_owned_mutex_count == ((UINT) 0)) | ||||
|                     { | ||||
|  | ||||
|                         /* Yes, the list is empty.  Simply set the head pointer to NULL.  */ | ||||
|                         thread_ptr -> tx_thread_owned_mutex_list =  TX_NULL; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|  | ||||
|                         /* No, there are more mutexes on the list.  */ | ||||
|  | ||||
|                         /* Link-up the neighbors.  */ | ||||
|                         next_mutex =                             mutex_ptr -> tx_mutex_owned_next; | ||||
|                         previous_mutex =                         mutex_ptr -> tx_mutex_owned_previous; | ||||
|                         next_mutex -> tx_mutex_owned_previous =  previous_mutex; | ||||
|                         previous_mutex -> tx_mutex_owned_next =  next_mutex; | ||||
|  | ||||
|                         /* See if we have to update the created list head pointer.  */ | ||||
|                         if (thread_ptr -> tx_thread_owned_mutex_list == mutex_ptr) | ||||
|                         { | ||||
|  | ||||
|                             /* Yes, move the head pointer to the next link. */ | ||||
|                             thread_ptr -> tx_thread_owned_mutex_list =  next_mutex; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     /* Determine if the simple, non-suspension, non-priority inheritance case is present.  */ | ||||
|                     if (mutex_ptr -> tx_mutex_suspension_list == TX_NULL) | ||||
|                     { | ||||
|  | ||||
|                         /* Is this a priority inheritance mutex?  */ | ||||
|                         if (mutex_ptr -> tx_mutex_inherit == TX_FALSE) | ||||
|                         { | ||||
|  | ||||
|                             /* Yes, we are done - set the mutex owner to NULL.   */ | ||||
|                             mutex_ptr -> tx_mutex_owner =  TX_NULL; | ||||
|  | ||||
|                             /* Restore interrupts.  */ | ||||
|                             TX_RESTORE | ||||
|  | ||||
|                             /* Mutex is now available, return successful status.  */ | ||||
|                             status =  TX_SUCCESS; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     /* Determine if the processing is complete.  */ | ||||
|                     if (status == TX_NOT_DONE) | ||||
|                     { | ||||
|  | ||||
|                         /* Initialize original owner and thread priority.  */ | ||||
|                         old_owner =      TX_NULL; | ||||
|                         old_priority =   thread_ptr -> tx_thread_user_priority; | ||||
|  | ||||
|                         /* Does this mutex support priority inheritance?  */ | ||||
|                         if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) | ||||
|                         { | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                             /* Temporarily disable preemption.  */ | ||||
|                             _tx_thread_preempt_disable++; | ||||
|  | ||||
|                             /* Restore interrupts.  */ | ||||
|                             TX_RESTORE | ||||
| #endif | ||||
|  | ||||
|                             /* Default the inheritance priority to disabled.  */ | ||||
|                             inheritance_priority =  ((UINT) TX_MAX_PRIORITIES); | ||||
|  | ||||
|                             /* Search the owned mutexes for this thread to determine the highest priority for this | ||||
|                                former mutex owner to return to.  */ | ||||
|                             next_mutex =  thread_ptr -> tx_thread_owned_mutex_list; | ||||
|                             while (next_mutex != TX_NULL) | ||||
|                             { | ||||
|  | ||||
|                                 /* Does this mutex support priority inheritance?  */ | ||||
|                                 if (next_mutex -> tx_mutex_inherit == TX_TRUE) | ||||
|                                 { | ||||
|  | ||||
|                                     /* Determine if highest priority field of the mutex is higher than the priority to | ||||
|                                        restore.  */ | ||||
|                                     if (next_mutex -> tx_mutex_highest_priority_waiting < inheritance_priority) | ||||
|                                     { | ||||
|  | ||||
|                                         /* Use this priority to return releasing thread to.  */ | ||||
|                                         inheritance_priority =   next_mutex -> tx_mutex_highest_priority_waiting; | ||||
|                                     } | ||||
|                                 } | ||||
|  | ||||
|                                 /* Move mutex pointer to the next mutex in the list.  */ | ||||
|                                 next_mutex =  next_mutex -> tx_mutex_owned_next; | ||||
|  | ||||
|                                 /* Are we at the end of the list?  */ | ||||
|                                 if (next_mutex == thread_ptr -> tx_thread_owned_mutex_list) | ||||
|                                 { | ||||
|  | ||||
|                                     /* Yes, set the next mutex to NULL.  */ | ||||
|                                     next_mutex =  TX_NULL; | ||||
|                                 } | ||||
|                             } | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                             /* Disable interrupts.  */ | ||||
|                             TX_DISABLE | ||||
|  | ||||
|                             /* Undo the temporarily preemption disable.  */ | ||||
|                             _tx_thread_preempt_disable--; | ||||
| #endif | ||||
|  | ||||
|                             /* Set the inherit priority to that of the highest priority thread waiting on the mutex.  */ | ||||
|                             thread_ptr -> tx_thread_inherit_priority =  inheritance_priority; | ||||
|  | ||||
|                             /* Determine if the inheritance priority is less than the default old priority.  */ | ||||
|                             if (inheritance_priority < old_priority) | ||||
|                             { | ||||
|  | ||||
|                                 /* Yes, update the old priority.  */ | ||||
|                                 old_priority =  inheritance_priority; | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         /* Determine if priority inheritance is in effect and there are one or more | ||||
|                            threads suspended on the mutex.  */ | ||||
|                         if (mutex_ptr -> tx_mutex_suspended_count > ((UINT) 1)) | ||||
|                         { | ||||
|  | ||||
|                             /* Is priority inheritance in effect?  */ | ||||
|                             if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) | ||||
|                             { | ||||
|  | ||||
|                                 /* Yes, this code is simply to ensure the highest priority thread is positioned | ||||
|                                    at the front of the suspension list.  */ | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                                 /* Temporarily disable preemption.  */ | ||||
|                                 _tx_thread_preempt_disable++; | ||||
|  | ||||
|                                 /* Restore interrupts.  */ | ||||
|                                 TX_RESTORE | ||||
| #endif | ||||
|  | ||||
|                                 /* Call the mutex prioritize processing to ensure the | ||||
|                                    highest priority thread is resumed.  */ | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|                                 do | ||||
|                                 { | ||||
|                                     status =  _tx_mutex_prioritize(mutex_ptr); | ||||
|                                 } while (status != TX_SUCCESS); | ||||
| #else | ||||
|                                 _tx_mutex_prioritize(mutex_ptr); | ||||
| #endif | ||||
|  | ||||
|                                 /* At this point, the highest priority thread is at the | ||||
|                                    front of the suspension list.  */ | ||||
|  | ||||
|                                 /* Optional processing extension.  */ | ||||
|                                 TX_MUTEX_PUT_EXTENSION_1 | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                                 /* Disable interrupts.  */ | ||||
|                                 TX_DISABLE | ||||
|  | ||||
|                                 /* Back off the preemption disable.  */ | ||||
|                                 _tx_thread_preempt_disable--; | ||||
| #endif | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         /* Now determine if there are any threads still waiting on the mutex.  */ | ||||
|                         if (mutex_ptr -> tx_mutex_suspension_list == TX_NULL) | ||||
|                         { | ||||
|  | ||||
|                             /* No, there are no longer any threads waiting on the mutex.  */ | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                             /* Temporarily disable preemption.  */ | ||||
|                             _tx_thread_preempt_disable++; | ||||
|  | ||||
|                             /* Restore interrupts.  */ | ||||
|                             TX_RESTORE | ||||
| #endif | ||||
|  | ||||
|                             /* Mutex is not owned, but it is possible that a thread that | ||||
|                                caused a priority inheritance to occur is no longer waiting | ||||
|                                on the mutex.  */ | ||||
|  | ||||
|                             /* Setup the highest priority waiting thread.  */ | ||||
|                             mutex_ptr -> tx_mutex_highest_priority_waiting =  (UINT) TX_MAX_PRIORITIES; | ||||
|  | ||||
|                             /* Determine if we need to restore priority.  */ | ||||
|                             if ((mutex_ptr -> tx_mutex_owner) -> tx_thread_priority != old_priority) | ||||
|                             { | ||||
|  | ||||
|                                 /* Yes, restore the priority of thread.  */ | ||||
|                                 _tx_mutex_priority_change(mutex_ptr -> tx_mutex_owner, old_priority); | ||||
|                             } | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                             /* Disable interrupts again.  */ | ||||
|                             TX_DISABLE | ||||
|  | ||||
|                             /* Back off the preemption disable.  */ | ||||
|                             _tx_thread_preempt_disable--; | ||||
| #endif | ||||
|  | ||||
|                             /* Set the mutex owner to NULL.  */ | ||||
|                             mutex_ptr -> tx_mutex_owner =  TX_NULL; | ||||
|  | ||||
|                             /* Restore interrupts.  */ | ||||
|                             TX_RESTORE | ||||
|  | ||||
|                             /* Check for preemption.  */ | ||||
|                             _tx_thread_system_preempt_check(); | ||||
|  | ||||
|                             /* Set status to success.  */ | ||||
|                             status =  TX_SUCCESS; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* Pickup the thread at the front of the suspension list.  */ | ||||
|                             thread_ptr =  mutex_ptr -> tx_mutex_suspension_list; | ||||
|  | ||||
|                             /* Save the previous ownership information, if inheritance is | ||||
|                                in effect.  */ | ||||
|                             if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) | ||||
|                             { | ||||
|  | ||||
|                                 /* Remember the old mutex owner.  */ | ||||
|                                 old_owner =  mutex_ptr -> tx_mutex_owner; | ||||
|  | ||||
|                                 /* Setup owner thread priority information.  */ | ||||
|                                 mutex_ptr -> tx_mutex_original_priority =   thread_ptr -> tx_thread_priority; | ||||
|  | ||||
|                                 /* Setup the highest priority waiting thread.  */ | ||||
|                                 mutex_ptr -> tx_mutex_highest_priority_waiting =  (UINT) TX_MAX_PRIORITIES; | ||||
|                             } | ||||
|  | ||||
|                             /* Determine how many mutexes are owned by this thread.  */ | ||||
|                             owned_count =  thread_ptr -> tx_thread_owned_mutex_count; | ||||
|  | ||||
|                             /* Determine if this thread owns any other mutexes that have priority inheritance.  */ | ||||
|                             if (owned_count == ((UINT) 0)) | ||||
|                             { | ||||
|  | ||||
|                                 /* The owned mutex list is empty.  Add mutex to empty list.  */ | ||||
|                                 thread_ptr -> tx_thread_owned_mutex_list =     mutex_ptr; | ||||
|                                 mutex_ptr -> tx_mutex_owned_next =             mutex_ptr; | ||||
|                                 mutex_ptr -> tx_mutex_owned_previous =         mutex_ptr; | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|  | ||||
|                                 /* Non-empty list. Link up the mutex.  */ | ||||
|  | ||||
|                                 /* Pickup tail pointer.  */ | ||||
|                                 next_mutex =                            thread_ptr -> tx_thread_owned_mutex_list; | ||||
|                                 previous_mutex =                        next_mutex -> tx_mutex_owned_previous; | ||||
|  | ||||
|                                 /* Place the owned mutex in the list.  */ | ||||
|                                 next_mutex -> tx_mutex_owned_previous =  mutex_ptr; | ||||
|                                 previous_mutex -> tx_mutex_owned_next =  mutex_ptr; | ||||
|  | ||||
|                                 /* Setup this mutex's next and previous created links.  */ | ||||
|                                 mutex_ptr -> tx_mutex_owned_previous =   previous_mutex; | ||||
|                                 mutex_ptr -> tx_mutex_owned_next =       next_mutex; | ||||
|                             } | ||||
|  | ||||
|                             /* Increment the number of mutexes owned counter.  */ | ||||
|                             thread_ptr -> tx_thread_owned_mutex_count =  owned_count + ((UINT) 1); | ||||
|  | ||||
|                             /* Mark the Mutex as owned and fill in the corresponding information.  */ | ||||
|                             mutex_ptr -> tx_mutex_ownership_count =  (UINT) 1; | ||||
|                             mutex_ptr -> tx_mutex_owner =            thread_ptr; | ||||
|  | ||||
|                             /* Remove the suspended thread from the list.  */ | ||||
|  | ||||
|                             /* Decrement the suspension count.  */ | ||||
|                             mutex_ptr -> tx_mutex_suspended_count--; | ||||
|  | ||||
|                             /* Pickup the suspended count.  */ | ||||
|                             suspended_count =  mutex_ptr -> tx_mutex_suspended_count; | ||||
|  | ||||
|                             /* See if this is the only suspended thread on the list.  */ | ||||
|                             if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|                             { | ||||
|  | ||||
|                                 /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|                                 /* Update the head pointer.  */ | ||||
|                                 mutex_ptr -> tx_mutex_suspension_list =  TX_NULL; | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|  | ||||
|                                 /* At least one more thread is on the same expiration list.  */ | ||||
|  | ||||
|                                 /* Update the list head pointer.  */ | ||||
|                                 next_thread =                                  thread_ptr -> tx_thread_suspended_next; | ||||
|                                 mutex_ptr -> tx_mutex_suspension_list =        next_thread; | ||||
|  | ||||
|                                 /* Update the links of the adjacent threads.  */ | ||||
|                                 previous_thread =                              thread_ptr -> tx_thread_suspended_previous; | ||||
|                                 next_thread -> tx_thread_suspended_previous =  previous_thread; | ||||
|                                 previous_thread -> tx_thread_suspended_next =  next_thread; | ||||
|                             } | ||||
|  | ||||
|                             /* Prepare for resumption of the first thread.  */ | ||||
|  | ||||
|                             /* Clear cleanup routine to avoid timeout.  */ | ||||
|                             thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|                             /* Put return status into the thread control block.  */ | ||||
|                             thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                             /* Determine if priority inheritance is enabled for this mutex.  */ | ||||
|                             if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) | ||||
|                             { | ||||
|  | ||||
|                                 /* Yes, priority inheritance is requested.  */ | ||||
|  | ||||
|                                 /* Determine if there are any more threads still suspended on the mutex.  */ | ||||
|                                 if (mutex_ptr -> tx_mutex_suspended_count != ((ULONG) 0)) | ||||
|                                 { | ||||
|  | ||||
|                                     /* Determine if there are more than one thread suspended on the mutex.  */ | ||||
|                                     if (mutex_ptr -> tx_mutex_suspended_count > ((ULONG) 1)) | ||||
|                                     { | ||||
|  | ||||
|                                         /* If so, prioritize the list so the highest priority thread is placed at the | ||||
|                                            front of the suspension list.  */ | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|                                         do | ||||
|                                         { | ||||
|                                             status =  _tx_mutex_prioritize(mutex_ptr); | ||||
|                                         } while (status != TX_SUCCESS); | ||||
| #else | ||||
|                                         _tx_mutex_prioritize(mutex_ptr); | ||||
| #endif | ||||
|                                     } | ||||
|  | ||||
|                                     /* Now, pickup the list head and set the priority.  */ | ||||
|  | ||||
|                                     /* Determine if there still are threads suspended for this mutex.  */ | ||||
|                                     suspended_thread =  mutex_ptr -> tx_mutex_suspension_list; | ||||
|                                     if (suspended_thread != TX_NULL) | ||||
|                                     { | ||||
|  | ||||
|                                         /* Setup the highest priority thread waiting on this mutex.  */ | ||||
|                                         mutex_ptr -> tx_mutex_highest_priority_waiting =  suspended_thread -> tx_thread_priority; | ||||
|                                     } | ||||
|                                 } | ||||
|  | ||||
|                                 /* Restore previous priority needs to be restored after priority | ||||
|                                    inheritance.  */ | ||||
|  | ||||
|                                 /* Determine if we need to restore priority.  */ | ||||
|                                 if (old_owner -> tx_thread_priority != old_priority) | ||||
|                                 { | ||||
|  | ||||
|                                     /* Restore priority of thread.  */ | ||||
|                                     _tx_mutex_priority_change(old_owner, old_priority); | ||||
|                                 } | ||||
|                             } | ||||
|  | ||||
|                             /* Resume the thread!  */ | ||||
|                             _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|                             /* Restore interrupts.  */ | ||||
|                             TX_RESTORE | ||||
| #else | ||||
|  | ||||
|                             /* Temporarily disable preemption.  */ | ||||
|                             _tx_thread_preempt_disable++; | ||||
|  | ||||
|                             /* Restore interrupts.  */ | ||||
|                             TX_RESTORE | ||||
|  | ||||
|                             /* Determine if priority inheritance is enabled for this mutex.  */ | ||||
|                             if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) | ||||
|                             { | ||||
|  | ||||
|                                 /* Yes, priority inheritance is requested.  */ | ||||
|  | ||||
|                                 /* Determine if there are any more threads still suspended on the mutex.  */ | ||||
|                                 if (mutex_ptr -> tx_mutex_suspended_count != TX_NO_SUSPENSIONS) | ||||
|                                 { | ||||
|  | ||||
|                                     /* Prioritize the list so the highest priority thread is placed at the | ||||
|                                        front of the suspension list.  */ | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|                                     do | ||||
|                                     { | ||||
|                                         status =  _tx_mutex_prioritize(mutex_ptr); | ||||
|                                     } while (status != TX_SUCCESS); | ||||
| #else | ||||
|                                     _tx_mutex_prioritize(mutex_ptr); | ||||
| #endif | ||||
|  | ||||
|                                     /* Now, pickup the list head and set the priority.  */ | ||||
|  | ||||
|                                     /* Optional processing extension.  */ | ||||
|                                     TX_MUTEX_PUT_EXTENSION_2 | ||||
|  | ||||
|                                     /* Disable interrupts.  */ | ||||
|                                     TX_DISABLE | ||||
|  | ||||
|                                     /* Determine if there still are threads suspended for this mutex.  */ | ||||
|                                     suspended_thread =  mutex_ptr -> tx_mutex_suspension_list; | ||||
|                                     if (suspended_thread != TX_NULL) | ||||
|                                     { | ||||
|  | ||||
|                                         /* Setup the highest priority thread waiting on this mutex.  */ | ||||
|                                         mutex_ptr -> tx_mutex_highest_priority_waiting =  suspended_thread -> tx_thread_priority; | ||||
|                                     } | ||||
|  | ||||
|                                     /* Restore interrupts.  */ | ||||
|                                     TX_RESTORE | ||||
|                                 } | ||||
|  | ||||
|                                 /* Restore previous priority needs to be restored after priority | ||||
|                                    inheritance.  */ | ||||
|  | ||||
|                                 /* Is the priority different?  */ | ||||
|                                 if (old_owner -> tx_thread_priority != old_priority) | ||||
|                                 { | ||||
|  | ||||
|                                     /* Restore the priority of thread.  */ | ||||
|                                     _tx_mutex_priority_change(old_owner, old_priority); | ||||
|                                 } | ||||
|                             } | ||||
|  | ||||
|                             /* Resume thread.  */ | ||||
|                             _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|                             /* Return a successful status.  */ | ||||
|                             status =  TX_SUCCESS; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Caller does not own the mutex.  */ | ||||
|         status =  TX_NOT_OWNED; | ||||
|     } | ||||
|  | ||||
|     /* Return the completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										227
									
								
								Middlewares/ST/threadx/common/src/tx_queue_cleanup.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								Middlewares/ST/threadx/common/src/tx_queue_cleanup.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,227 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Queue                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_queue.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_queue_cleanup                                   PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function processes queue timeout and thread terminate          */ | ||||
| /*    actions that require the queue data structures to be cleaned        */ | ||||
| /*    up.                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                        Pointer to suspended thread's     */ | ||||
| /*                                        control block                   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_timeout                Thread timeout processing         */ | ||||
| /*    _tx_thread_terminate              Thread terminate processing       */ | ||||
| /*    _tx_thread_wait_abort             Thread wait abort processing      */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_queue_cleanup(TX_THREAD  *thread_ptr, ULONG suspension_sequence) | ||||
| { | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
| #endif | ||||
|  | ||||
| TX_QUEUE            *queue_ptr; | ||||
| UINT                suspended_count; | ||||
| TX_THREAD           *next_thread; | ||||
| TX_THREAD           *previous_thread; | ||||
|  | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|     /* Disable interrupts to remove the suspended thread from the queue.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Determine if the cleanup is still required.  */ | ||||
|     if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_queue_cleanup)) | ||||
|     { | ||||
|  | ||||
|         /* Check for valid suspension sequence.  */ | ||||
|         if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence) | ||||
|         { | ||||
|  | ||||
|             /* Setup pointer to queue control block.  */ | ||||
|             queue_ptr =  TX_VOID_TO_QUEUE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); | ||||
|  | ||||
|             /* Check for NULL queue pointer.  */ | ||||
|             if (queue_ptr != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Is the queue ID valid?  */ | ||||
|                 if (queue_ptr -> tx_queue_id == TX_QUEUE_ID) | ||||
|                 { | ||||
|  | ||||
|                     /* Determine if there are any thread suspensions.  */ | ||||
|                     if (queue_ptr -> tx_queue_suspended_count != TX_NO_SUSPENSIONS) | ||||
|                     { | ||||
| #else | ||||
|  | ||||
|                         /* Setup pointer to queue control block.  */ | ||||
|                         queue_ptr =  TX_VOID_TO_QUEUE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); | ||||
| #endif | ||||
|  | ||||
|                         /* Yes, we still have thread suspension!  */ | ||||
|  | ||||
|                         /* Clear the suspension cleanup flag.  */ | ||||
|                         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|                         /* Decrement the suspended count.  */ | ||||
|                         queue_ptr -> tx_queue_suspended_count--; | ||||
|  | ||||
|                         /* Pickup the suspended count.  */ | ||||
|                         suspended_count =  queue_ptr -> tx_queue_suspended_count; | ||||
|  | ||||
|                         /* Remove the suspended thread from the list.  */ | ||||
|  | ||||
|                         /* See if this is the only suspended thread on the list.  */ | ||||
|                         if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|                         { | ||||
|  | ||||
|                             /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|                             /* Update the head pointer.  */ | ||||
|                             queue_ptr -> tx_queue_suspension_list =  TX_NULL; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* At least one more thread is on the same suspension list.  */ | ||||
|  | ||||
|                             /* Update the links of the adjacent threads.  */ | ||||
|                             next_thread =                                   thread_ptr -> tx_thread_suspended_next; | ||||
|                             previous_thread =                               thread_ptr -> tx_thread_suspended_previous; | ||||
|                             next_thread -> tx_thread_suspended_previous =   previous_thread; | ||||
|                             previous_thread -> tx_thread_suspended_next =   next_thread; | ||||
|  | ||||
|                             /* Determine if we need to update the head pointer.  */ | ||||
|                             if (queue_ptr -> tx_queue_suspension_list == thread_ptr) | ||||
|                             { | ||||
|  | ||||
|                                 /* Update the list head pointer.  */ | ||||
|                                 queue_ptr -> tx_queue_suspension_list =         next_thread; | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         /* Now we need to determine if this cleanup is from a terminate, timeout, | ||||
|                            or from a wait abort.  */ | ||||
|                         if (thread_ptr -> tx_thread_state == TX_QUEUE_SUSP) | ||||
|                         { | ||||
|  | ||||
|                             /* Timeout condition and the thread still suspended on the queue. | ||||
|                                Setup return error status and resume the thread.  */ | ||||
|  | ||||
| #ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                             /* Increment the total timeouts counter.  */ | ||||
|                             _tx_queue_performance_timeout_count++; | ||||
|  | ||||
|                             /* Increment the number of timeouts on this queue.  */ | ||||
|                             queue_ptr -> tx_queue_performance_timeout_count++; | ||||
| #endif | ||||
|  | ||||
|                             /* Setup return status.  */ | ||||
|                             if (queue_ptr -> tx_queue_enqueued != TX_NO_MESSAGES) | ||||
|                             { | ||||
|  | ||||
|                                 /* Queue full timeout!  */ | ||||
|                                 thread_ptr -> tx_thread_suspend_status =  TX_QUEUE_FULL; | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|  | ||||
|                                 /* Queue empty timeout!  */ | ||||
|                                 thread_ptr -> tx_thread_suspend_status =  TX_QUEUE_EMPTY; | ||||
|                             } | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                             /* Resume the thread!  */ | ||||
|                             _tx_thread_system_ni_resume(thread_ptr); | ||||
| #else | ||||
|  | ||||
|                             /* Temporarily disable preemption.  */ | ||||
|                             _tx_thread_preempt_disable++; | ||||
|  | ||||
|                             /* Restore interrupts.  */ | ||||
|                             TX_RESTORE | ||||
|  | ||||
|                             /* Resume the thread!  */ | ||||
|                             _tx_thread_system_resume(thread_ptr); | ||||
|  | ||||
|                             /* Disable interrupts.  */ | ||||
|                             TX_DISABLE | ||||
| #endif | ||||
|                         } | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										172
									
								
								Middlewares/ST/threadx/common/src/tx_queue_create.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								Middlewares/ST/threadx/common/src/tx_queue_create.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,172 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Queue                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_queue.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_queue_create                                    PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function creates a message queue.  The message size and depth  */ | ||||
| /*    of the queue is specified by the caller.                            */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    queue_ptr                         Pointer to queue control block    */ | ||||
| /*    name_ptr                          Pointer to queue name             */ | ||||
| /*    message_size                      Size of each queue message        */ | ||||
| /*    queue_start                       Starting address of the queue area*/ | ||||
| /*    queue_size                        Number of bytes in the queue      */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, | ||||
|                         VOID *queue_start, ULONG queue_size) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| UINT            capacity; | ||||
| UINT            used_words; | ||||
| TX_QUEUE        *next_queue; | ||||
| TX_QUEUE        *previous_queue; | ||||
|  | ||||
|  | ||||
|     /* Initialize queue control block to all zeros.  */ | ||||
|     TX_MEMSET(queue_ptr, 0, (sizeof(TX_QUEUE))); | ||||
|  | ||||
|     /* Setup the basic queue fields.  */ | ||||
|     queue_ptr -> tx_queue_name =             name_ptr; | ||||
|  | ||||
|     /* Save the message size in the control block.  */ | ||||
|     queue_ptr -> tx_queue_message_size =  message_size; | ||||
|  | ||||
|     /* Determine how many messages will fit in the queue area and the number | ||||
|        of ULONGs used.  */ | ||||
|     capacity =    (UINT) (queue_size / ((ULONG) (((ULONG) message_size) * (sizeof(ULONG))))); | ||||
|     used_words =  capacity * message_size; | ||||
|  | ||||
|     /* Save the starting address and calculate the ending address of | ||||
|        the queue.  Note that the ending address is really one past the | ||||
|        end!  */ | ||||
|     queue_ptr -> tx_queue_start =  TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start); | ||||
|     queue_ptr -> tx_queue_end =    TX_ULONG_POINTER_ADD(queue_ptr -> tx_queue_start, used_words); | ||||
|  | ||||
|     /* Set the read and write pointers to the beginning of the queue | ||||
|        area.  */ | ||||
|     queue_ptr -> tx_queue_read =   TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start); | ||||
|     queue_ptr -> tx_queue_write =  TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start); | ||||
|  | ||||
|     /* Setup the number of enqueued messages and the number of message | ||||
|        slots available in the queue.  */ | ||||
|     queue_ptr -> tx_queue_available_storage =  (UINT) capacity; | ||||
|     queue_ptr -> tx_queue_capacity =           (UINT) capacity; | ||||
|  | ||||
|     /* Disable interrupts to put the queue on the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Setup the queue ID to make it valid.  */ | ||||
|     queue_ptr -> tx_queue_id =  TX_QUEUE_ID; | ||||
|  | ||||
|     /* Place the queue on the list of created queues.  First, | ||||
|        check for an empty list.  */ | ||||
|     if (_tx_queue_created_count == TX_EMPTY) | ||||
|     { | ||||
|  | ||||
|         /* The created queue list is empty.  Add queue to empty list.  */ | ||||
|         _tx_queue_created_ptr =                   queue_ptr; | ||||
|         queue_ptr -> tx_queue_created_next =      queue_ptr; | ||||
|         queue_ptr -> tx_queue_created_previous =  queue_ptr; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* This list is not NULL, add to the end of the list.  */ | ||||
|         next_queue =      _tx_queue_created_ptr; | ||||
|         previous_queue =  next_queue -> tx_queue_created_previous; | ||||
|  | ||||
|         /* Place the new queue in the list.  */ | ||||
|         next_queue -> tx_queue_created_previous =  queue_ptr; | ||||
|         previous_queue -> tx_queue_created_next =  queue_ptr; | ||||
|  | ||||
|         /* Setup this queues's created links.  */ | ||||
|         queue_ptr -> tx_queue_created_previous =  previous_queue; | ||||
|         queue_ptr -> tx_queue_created_next =      next_queue; | ||||
|     } | ||||
|  | ||||
|     /* Increment the created queue count.  */ | ||||
|     _tx_queue_created_count++; | ||||
|  | ||||
|     /* Optional queue create extended processing.  */ | ||||
|     TX_QUEUE_CREATE_EXTENSION(queue_ptr) | ||||
|  | ||||
|     /* If trace is enabled, register this object.  */ | ||||
|     TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_QUEUE, queue_ptr, name_ptr, queue_size, message_size) | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_CREATE, queue_ptr, message_size, TX_POINTER_TO_ULONG_CONVERT(queue_start), queue_size, TX_TRACE_QUEUE_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_QUEUE_CREATE_INSERT | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										208
									
								
								Middlewares/ST/threadx/common/src/tx_queue_delete.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								Middlewares/ST/threadx/common/src/tx_queue_delete.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,208 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Queue                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_queue.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_queue_delete                                    PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function deletes the specified queue.  All threads suspended   */ | ||||
| /*    on the queue are resumed with the TX_DELETED status code.           */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    queue_ptr                         Pointer to queue control block    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_queue_delete(TX_QUEUE *queue_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_THREAD       *next_thread; | ||||
| UINT            suspended_count; | ||||
| TX_QUEUE        *next_queue; | ||||
| TX_QUEUE        *previous_queue; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to remove the queue from the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_DELETE, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_QUEUE_EVENTS) | ||||
|  | ||||
|     /* Optional queue delete extended processing.  */ | ||||
|     TX_QUEUE_DELETE_EXTENSION(queue_ptr) | ||||
|  | ||||
|     /* If trace is enabled, unregister this object.  */ | ||||
|     TX_TRACE_OBJECT_UNREGISTER(queue_ptr) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_QUEUE_DELETE_INSERT | ||||
|  | ||||
|     /* Clear the queue ID to make it invalid.  */ | ||||
|     queue_ptr -> tx_queue_id =  TX_CLEAR_ID; | ||||
|  | ||||
|     /* Decrement the number of created queues.  */ | ||||
|     _tx_queue_created_count--; | ||||
|  | ||||
|     /* See if the queue is the only one on the list.  */ | ||||
|     if (_tx_queue_created_count == TX_EMPTY) | ||||
|     { | ||||
|  | ||||
|         /* Only created queue, just set the created list to NULL.  */ | ||||
|         _tx_queue_created_ptr =  TX_NULL; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Link-up the neighbors.  */ | ||||
|         next_queue =                               queue_ptr -> tx_queue_created_next; | ||||
|         previous_queue =                           queue_ptr -> tx_queue_created_previous; | ||||
|         next_queue -> tx_queue_created_previous =  previous_queue; | ||||
|         previous_queue -> tx_queue_created_next =  next_queue; | ||||
|  | ||||
|         /* See if we have to update the created list head pointer.  */ | ||||
|         if (_tx_queue_created_ptr == queue_ptr) | ||||
|         { | ||||
|  | ||||
|             /* Yes, move the head pointer to the next link. */ | ||||
|             _tx_queue_created_ptr =  next_queue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Temporarily disable preemption.  */ | ||||
|     _tx_thread_preempt_disable++; | ||||
|  | ||||
|     /* Pickup the suspension information.  */ | ||||
|     thread_ptr =                             queue_ptr -> tx_queue_suspension_list; | ||||
|     queue_ptr -> tx_queue_suspension_list =  TX_NULL; | ||||
|     suspended_count =                        queue_ptr -> tx_queue_suspended_count; | ||||
|     queue_ptr -> tx_queue_suspended_count =  TX_NO_SUSPENSIONS; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Walk through the queue list to resume any and all threads suspended | ||||
|        on this queue.  */ | ||||
|     while (suspended_count != TX_NO_SUSPENSIONS) | ||||
|     { | ||||
|  | ||||
|         /* Decrement the suspension count.  */ | ||||
|         suspended_count--; | ||||
|  | ||||
|         /* Lockout interrupts.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* Clear the cleanup pointer, this prevents the timeout from doing | ||||
|            anything.  */ | ||||
|         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|         /* Set the return status in the thread to TX_DELETED.  */ | ||||
|         thread_ptr -> tx_thread_suspend_status =  TX_DELETED; | ||||
|  | ||||
|         /* Move the thread pointer ahead.  */ | ||||
|         next_thread =  thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Resume the thread!  */ | ||||
|         _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #else | ||||
|  | ||||
|         /* Temporarily disable preemption again.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Resume the thread.  */ | ||||
|         _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|         /* Move to next thread.  */ | ||||
|         thread_ptr =  next_thread; | ||||
|     } | ||||
|  | ||||
|     /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h.  */ | ||||
|     TX_QUEUE_DELETE_PORT_COMPLETION(queue_ptr) | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Release previous preempt disable.  */ | ||||
|     _tx_thread_preempt_disable--; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Check for preemption.  */ | ||||
|     _tx_thread_system_preempt_check(); | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										207
									
								
								Middlewares/ST/threadx/common/src/tx_queue_flush.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								Middlewares/ST/threadx/common/src/tx_queue_flush.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,207 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Queue                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_queue.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_queue_flush                                     PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function resets the specified queue, if there are any messages */ | ||||
| /*    in it.  Messages waiting to be placed on the queue are also thrown  */ | ||||
| /*    out.                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    queue_ptr                         Pointer to queue control block    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_queue_flush(TX_QUEUE *queue_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *suspension_list; | ||||
| UINT            suspended_count; | ||||
| TX_THREAD       *thread_ptr; | ||||
|  | ||||
|  | ||||
|     /* Initialize the suspended count and list.  */ | ||||
|     suspended_count =  TX_NO_SUSPENSIONS; | ||||
|     suspension_list =  TX_NULL; | ||||
|  | ||||
|     /* Disable interrupts to reset various queue parameters.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_FLUSH, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_QUEUE_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_QUEUE_FLUSH_INSERT | ||||
|  | ||||
|     /* Determine if there is something on the queue.  */ | ||||
|     if (queue_ptr -> tx_queue_enqueued != TX_NO_MESSAGES) | ||||
|     { | ||||
|  | ||||
|         /* Yes, there is something in the queue.  */ | ||||
|  | ||||
|         /* Reset the queue parameters to erase all of the queued messages.  */ | ||||
|         queue_ptr -> tx_queue_enqueued =           TX_NO_MESSAGES; | ||||
|         queue_ptr -> tx_queue_available_storage =  queue_ptr -> tx_queue_capacity; | ||||
|         queue_ptr -> tx_queue_read =               queue_ptr -> tx_queue_start; | ||||
|         queue_ptr -> tx_queue_write =              queue_ptr -> tx_queue_start; | ||||
|  | ||||
|         /* Now determine if there are any threads suspended on a full queue.  */ | ||||
|         if (queue_ptr -> tx_queue_suspended_count != TX_NO_SUSPENSIONS) | ||||
|         { | ||||
|  | ||||
|             /* Yes, there are threads suspended on this queue, they must be | ||||
|                resumed!  */ | ||||
|  | ||||
|             /* Copy the information into temporary variables.  */ | ||||
|             suspension_list =  queue_ptr -> tx_queue_suspension_list; | ||||
|             suspended_count =  queue_ptr -> tx_queue_suspended_count; | ||||
|  | ||||
|             /* Clear the queue variables.  */ | ||||
|             queue_ptr -> tx_queue_suspension_list =  TX_NULL; | ||||
|             queue_ptr -> tx_queue_suspended_count =  TX_NO_SUSPENSIONS; | ||||
|  | ||||
|             /* Temporarily disable preemption.  */ | ||||
|             _tx_thread_preempt_disable++; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Walk through the queue list to resume any and all threads suspended | ||||
|        on this queue.  */ | ||||
|     if (suspended_count != TX_NO_SUSPENSIONS) | ||||
|     { | ||||
|  | ||||
|         /* Pickup the thread to resume.  */ | ||||
|         thread_ptr =  suspension_list; | ||||
|         while (suspended_count != ((ULONG) 0)) | ||||
|         { | ||||
|  | ||||
|             /* Decrement the suspension count.  */ | ||||
|             suspended_count--; | ||||
|  | ||||
|             /* Check for a NULL thread pointer.  */ | ||||
|             if (thread_ptr == TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Get out of the loop.  */ | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             /* Resume the next suspended thread.  */ | ||||
|  | ||||
|             /* Lockout interrupts.  */ | ||||
|             TX_DISABLE | ||||
|  | ||||
|             /* Clear the cleanup pointer, this prevents the timeout from doing | ||||
|                anything.  */ | ||||
|             thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|             /* Set the return status in the thread to TX_SUCCESS.  */ | ||||
|             thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS; | ||||
|  | ||||
|             /* Move the thread pointer ahead.  */ | ||||
|             thread_ptr =  thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Resume the thread!  */ | ||||
|             _tx_thread_system_ni_resume(thread_ptr -> tx_thread_suspended_previous); | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #else | ||||
|  | ||||
|             /* Temporarily disable preemption again.  */ | ||||
|             _tx_thread_preempt_disable++; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Resume the thread.  */ | ||||
|             _tx_thread_system_resume(thread_ptr -> tx_thread_suspended_previous); | ||||
| #endif | ||||
|         } | ||||
|  | ||||
|         /* Disable interrupts.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* Restore previous preempt posture.  */ | ||||
|         _tx_thread_preempt_disable--; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Check for preemption.  */ | ||||
|         _tx_thread_system_preempt_check(); | ||||
|     } | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										423
									
								
								Middlewares/ST/threadx/common/src/tx_queue_front_send.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										423
									
								
								Middlewares/ST/threadx/common/src/tx_queue_front_send.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,423 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Queue                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_queue.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_queue_front_send                                PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function places a message at the front of the specified queue. */ | ||||
| /*    If there is no room in the queue, this function returns the         */ | ||||
| /*    queue full status.                                                  */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    queue_ptr                         Pointer to queue control block    */ | ||||
| /*    source_ptr                        Pointer to message source         */ | ||||
| /*    wait_option                       Suspension option                 */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread routine             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*    _tx_thread_system_suspend         Suspend thread routine            */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| ULONG           *source; | ||||
| ULONG           *destination; | ||||
| UINT            size; | ||||
| UINT            suspended_count; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| UINT            status; | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
| VOID            (*queue_send_notify)(struct TX_QUEUE_STRUCT *notify_queue_ptr); | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     /* Default the status to TX_SUCCESS.  */ | ||||
|     status =  TX_SUCCESS; | ||||
|  | ||||
|     /* Disable interrupts to place message in the queue.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Increment the total messages sent counter.  */ | ||||
|     _tx_queue_performance_messages_sent_count++; | ||||
|  | ||||
|     /* Increment the number of messages sent to this queue.  */ | ||||
|     queue_ptr -> tx_queue_performance_messages_sent_count++; | ||||
| #endif | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_FRONT_SEND, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(source_ptr), wait_option, queue_ptr -> tx_queue_enqueued, TX_TRACE_QUEUE_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_QUEUE_FRONT_SEND_INSERT | ||||
|  | ||||
|     /* Pickup the suspended count.  */ | ||||
|     suspended_count =  queue_ptr -> tx_queue_suspended_count; | ||||
|  | ||||
|     /* Now check for room in the queue for placing the new message in front.  */ | ||||
|     if (queue_ptr -> tx_queue_available_storage != ((UINT) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Yes there is room in the queue. Now determine if there is a thread waiting | ||||
|            for a message.  */ | ||||
|         if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|         { | ||||
|  | ||||
|             /* No thread suspended while waiting for a message from | ||||
|                this queue.  */ | ||||
|  | ||||
|             /* Adjust the read pointer since we are adding to the front of the | ||||
|                queue.  */ | ||||
|  | ||||
|             /* See if the read pointer is at the beginning of the queue area.  */ | ||||
|             if (queue_ptr -> tx_queue_read == queue_ptr -> tx_queue_start) | ||||
|             { | ||||
|  | ||||
|                 /* Adjust the read pointer to the last message at the end of the | ||||
|                    queue.  */ | ||||
|                 queue_ptr -> tx_queue_read =  TX_ULONG_POINTER_SUB(queue_ptr -> tx_queue_end, queue_ptr -> tx_queue_message_size); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Not at the beginning of the queue, just move back one message.  */ | ||||
|                 queue_ptr -> tx_queue_read =  TX_ULONG_POINTER_SUB(queue_ptr -> tx_queue_read, queue_ptr -> tx_queue_message_size); | ||||
|             } | ||||
|  | ||||
|             /* Simply place the message in the queue.  */ | ||||
|  | ||||
|             /* Reduce the amount of available storage.  */ | ||||
|             queue_ptr -> tx_queue_available_storage--; | ||||
|  | ||||
|             /* Increase the enqueued count.  */ | ||||
|             queue_ptr -> tx_queue_enqueued++; | ||||
|  | ||||
|             /* Setup source and destination pointers.  */ | ||||
|             source =       TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr); | ||||
|             destination =  queue_ptr -> tx_queue_read; | ||||
|             size =         queue_ptr -> tx_queue_message_size; | ||||
|  | ||||
|             /* Copy message. Note that the source and destination pointers are | ||||
|                incremented by the macro.  */ | ||||
|             TX_QUEUE_MESSAGE_COPY(source, destination, size) | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Pickup the notify callback routine for this queue.  */ | ||||
|             queue_send_notify =  queue_ptr -> tx_queue_send_notify; | ||||
| #endif | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Determine if a notify callback is required.  */ | ||||
|             if (queue_send_notify != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Call application queue send notification.  */ | ||||
|                 (queue_send_notify)(queue_ptr); | ||||
|             } | ||||
| #endif | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Thread suspended waiting for a message.  Remove it and copy this message | ||||
|                into its storage area.  */ | ||||
|             thread_ptr =  queue_ptr -> tx_queue_suspension_list; | ||||
|  | ||||
|             /* See if this is the only suspended thread on the list.  */ | ||||
|             suspended_count--; | ||||
|             if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|                 /* Update the head pointer.  */ | ||||
|                 queue_ptr -> tx_queue_suspension_list =  TX_NULL; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* At least one more thread is on the same expiration list.  */ | ||||
|  | ||||
|                 /* Update the list head pointer.  */ | ||||
|                 queue_ptr -> tx_queue_suspension_list =  thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|                 /* Update the links of the adjacent threads.  */ | ||||
|                 next_thread =                            thread_ptr -> tx_thread_suspended_next; | ||||
|                 queue_ptr -> tx_queue_suspension_list =  next_thread; | ||||
|  | ||||
|                 /* Update the links of the adjacent threads.  */ | ||||
|                 previous_thread =                               thread_ptr -> tx_thread_suspended_previous; | ||||
|                 next_thread -> tx_thread_suspended_previous =   previous_thread; | ||||
|                 previous_thread -> tx_thread_suspended_next =   next_thread; | ||||
|             } | ||||
|  | ||||
|             /* Decrement the suspension count.  */ | ||||
|             queue_ptr -> tx_queue_suspended_count =  suspended_count; | ||||
|  | ||||
|             /* Prepare for resumption of the thread.  */ | ||||
|  | ||||
|             /* Clear cleanup routine to avoid timeout.  */ | ||||
|             thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Pickup the notify callback routine for this queue.  */ | ||||
|             queue_send_notify =  queue_ptr -> tx_queue_send_notify; | ||||
| #endif | ||||
|  | ||||
|             /* Setup source and destination pointers.  */ | ||||
|             source =       TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr); | ||||
|             destination =  TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info); | ||||
|             size =         queue_ptr -> tx_queue_message_size; | ||||
|  | ||||
|             /* Copy message. Note that the source and destination pointers are | ||||
|                incremented by the macro.  */ | ||||
|             TX_QUEUE_MESSAGE_COPY(source, destination, size) | ||||
|  | ||||
|             /* Put return status into the thread control block.  */ | ||||
|             thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Resume the thread!  */ | ||||
|             _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #else | ||||
|  | ||||
|             /* Temporarily disable preemption.  */ | ||||
|             _tx_thread_preempt_disable++; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Resume thread.  */ | ||||
|             _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Determine if a notify callback is required.  */ | ||||
|             if (queue_send_notify != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Call application queue send notification.  */ | ||||
|                 (queue_send_notify)(queue_ptr); | ||||
|             } | ||||
| #endif | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Determine if the caller has requested suspension.  */ | ||||
|     else if (wait_option != TX_NO_WAIT) | ||||
|     { | ||||
|  | ||||
|         /* Determine if the preempt disable flag is non-zero.  */ | ||||
|         if (_tx_thread_preempt_disable != ((UINT) 0)) | ||||
|         { | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion.  */ | ||||
|             status =  TX_QUEUE_FULL; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Yes, suspension is requested.  */ | ||||
|  | ||||
|             /* Prepare for suspension of this thread.  */ | ||||
|  | ||||
|             /* Pickup thread pointer.  */ | ||||
|             TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
|             /* Setup cleanup routine pointer.  */ | ||||
|             thread_ptr -> tx_thread_suspend_cleanup =  &(_tx_queue_cleanup); | ||||
|  | ||||
|             /* Setup cleanup information, i.e. this queue control | ||||
|                block and the source pointer.  */ | ||||
|             thread_ptr -> tx_thread_suspend_control_block =    (VOID *) queue_ptr; | ||||
|             thread_ptr -> tx_thread_additional_suspend_info =  (VOID *) source_ptr; | ||||
|  | ||||
|             /* Set the flag to true to indicate a queue front send suspension.  */ | ||||
|             thread_ptr -> tx_thread_suspend_option =           TX_TRUE; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Increment the suspension sequence number, which is used to identify | ||||
|                this suspension event.  */ | ||||
|             thread_ptr -> tx_thread_suspension_sequence++; | ||||
| #endif | ||||
|  | ||||
|             /* Place this thread at the front of the suspension list, since it is a | ||||
|                queue front send suspension.  */ | ||||
|             if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|             { | ||||
|  | ||||
|                 /* No other threads are suspended.  Setup the head pointer and | ||||
|                    just setup this threads pointers to itself.  */ | ||||
|                 queue_ptr -> tx_queue_suspension_list =         thread_ptr; | ||||
|                 thread_ptr -> tx_thread_suspended_next =        thread_ptr; | ||||
|                 thread_ptr -> tx_thread_suspended_previous =    thread_ptr; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* This list is not NULL, add current thread to the end. */ | ||||
|                 next_thread =                                   queue_ptr -> tx_queue_suspension_list; | ||||
|                 thread_ptr -> tx_thread_suspended_next =        next_thread; | ||||
|                 previous_thread =                               next_thread -> tx_thread_suspended_previous; | ||||
|                 thread_ptr -> tx_thread_suspended_previous =    previous_thread; | ||||
|                 previous_thread -> tx_thread_suspended_next =   thread_ptr; | ||||
|                 next_thread -> tx_thread_suspended_previous =   thread_ptr; | ||||
|  | ||||
|                 /* Update the suspension list to put this thread in front, which will put | ||||
|                    the message that was removed in the proper relative order when room is | ||||
|                    made in the queue.  */ | ||||
|                 queue_ptr -> tx_queue_suspension_list =         thread_ptr; | ||||
|             } | ||||
|  | ||||
|             /* Increment the suspended thread count.  */ | ||||
|             queue_ptr -> tx_queue_suspended_count =  suspended_count + ((UINT) 1); | ||||
|  | ||||
|             /* Set the state to suspended.  */ | ||||
|             thread_ptr -> tx_thread_state =    TX_QUEUE_SUSP; | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Pickup the notify callback routine for this queue.  */ | ||||
|             queue_send_notify =  queue_ptr -> tx_queue_send_notify; | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Call actual non-interruptable thread suspension routine.  */ | ||||
|             _tx_thread_system_ni_suspend(thread_ptr, wait_option); | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #else | ||||
|  | ||||
|             /* Set the suspending flag.  */ | ||||
|             thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|             /* Setup the timeout period.  */ | ||||
|             thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  wait_option; | ||||
|  | ||||
|             /* Temporarily disable preemption.  */ | ||||
|             _tx_thread_preempt_disable++; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Call actual thread suspension routine.  */ | ||||
|             _tx_thread_system_suspend(thread_ptr); | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Determine if a notify callback is required.  */ | ||||
|             if (thread_ptr -> tx_thread_suspend_status == TX_SUCCESS) | ||||
|             { | ||||
|  | ||||
|                 /* Check for a notify callback.  */ | ||||
|                 if (queue_send_notify != TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     /* Call application queue send notification.  */ | ||||
|                     (queue_send_notify)(queue_ptr); | ||||
|                 } | ||||
|             } | ||||
| #endif | ||||
|  | ||||
|             /* Return the completion status.  */ | ||||
|             status =  thread_ptr -> tx_thread_suspend_status; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* No room in queue and no suspension requested, return error completion.  */ | ||||
|         status =  TX_QUEUE_FULL; | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										147
									
								
								Middlewares/ST/threadx/common/src/tx_queue_info_get.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								Middlewares/ST/threadx/common/src/tx_queue_info_get.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,147 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Queue                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_queue.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_queue_info_get                                  PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function retrieves information from the specified queue.       */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    queue_ptr                         Pointer to queue control block    */ | ||||
| /*    name                              Destination for the queue name    */ | ||||
| /*    enqueued                          Destination for enqueued count    */ | ||||
| /*    available_storage                 Destination for available storage */ | ||||
| /*    first_suspended                   Destination for pointer of first  */ | ||||
| /*                                        thread suspended on this queue  */ | ||||
| /*    suspended_count                   Destination for suspended count   */ | ||||
| /*    next_queue                        Destination for pointer to next   */ | ||||
| /*                                        queue on the created list       */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage, | ||||
|                     TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_INFO_GET, queue_ptr, 0, 0, 0, TX_TRACE_QUEUE_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_QUEUE_INFO_GET_INSERT | ||||
|  | ||||
|     /* Retrieve all the pertinent information and return it in the supplied | ||||
|        destinations.  */ | ||||
|  | ||||
|     /* Retrieve the name of the queue.  */ | ||||
|     if (name != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *name =  queue_ptr -> tx_queue_name; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the number of messages currently in the queue.  */ | ||||
|     if (enqueued != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *enqueued =  (ULONG) queue_ptr -> tx_queue_enqueued; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the number of messages that will still fit in the queue.  */ | ||||
|     if (available_storage != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *available_storage =  (ULONG) queue_ptr -> tx_queue_available_storage; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the first thread suspended on this queue.  */ | ||||
|     if (first_suspended != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *first_suspended =  queue_ptr -> tx_queue_suspension_list; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the number of threads suspended on this queue.  */ | ||||
|     if (suspended_count != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *suspended_count =  (ULONG) queue_ptr -> tx_queue_suspended_count; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the pointer to the next queue created.  */ | ||||
|     if (next_queue != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *next_queue =  queue_ptr -> tx_queue_created_next; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										142
									
								
								Middlewares/ST/threadx/common/src/tx_queue_initialize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								Middlewares/ST/threadx/common/src/tx_queue_initialize.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,142 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Queue                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_queue.h" | ||||
|  | ||||
|  | ||||
| #ifndef TX_INLINE_INITIALIZATION | ||||
|  | ||||
| /* Define the head pointer of the created queue list.  */ | ||||
|  | ||||
| TX_QUEUE *   _tx_queue_created_ptr; | ||||
|  | ||||
|  | ||||
| /* Define the variable that holds the number of created queues. */ | ||||
|  | ||||
| ULONG        _tx_queue_created_count; | ||||
|  | ||||
|  | ||||
| #ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
| /* Define the total number of messages sent.  */ | ||||
|  | ||||
| ULONG        _tx_queue_performance_messages_sent_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of messages received.  */ | ||||
|  | ||||
| ULONG        _tx_queue_performance__messages_received_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of queue empty suspensions.  */ | ||||
|  | ||||
| ULONG        _tx_queue_performance_empty_suspension_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of queue full suspensions.  */ | ||||
|  | ||||
| ULONG        _tx_queue_performance_full_suspension_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of queue full errors.  */ | ||||
|  | ||||
| ULONG        _tx_queue_performance_full_error_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of queue timeouts.  */ | ||||
|  | ||||
| ULONG        _tx_queue_performance_timeout_count; | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_queue_initialize                                PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function initializes the various control data structures for   */ | ||||
| /*    the queue component.                                                */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_initialize_high_level         High level initialization         */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            opt out of function when    */ | ||||
| /*                                            TX_INLINE_INITIALIZATION is */ | ||||
| /*                                            defined,                    */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_queue_initialize(VOID) | ||||
| { | ||||
|  | ||||
| #ifndef TX_DISABLE_REDUNDANT_CLEARING | ||||
|  | ||||
|     /* Initialize the head pointer of the created queue list and the | ||||
|        number of queues created.  */ | ||||
|     _tx_queue_created_ptr =        TX_NULL; | ||||
|     _tx_queue_created_count =      TX_EMPTY; | ||||
|  | ||||
| #ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Initialize the queue performance counters.  */ | ||||
|     _tx_queue_performance_messages_sent_count =       ((ULONG) 0); | ||||
|     _tx_queue_performance__messages_received_count =  ((ULONG) 0); | ||||
|     _tx_queue_performance_empty_suspension_count =    ((ULONG) 0); | ||||
|     _tx_queue_performance_full_suspension_count =     ((ULONG) 0); | ||||
|     _tx_queue_performance_timeout_count =             ((ULONG) 0); | ||||
| #endif | ||||
| #endif | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										251
									
								
								Middlewares/ST/threadx/common/src/tx_queue_prioritize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										251
									
								
								Middlewares/ST/threadx/common/src/tx_queue_prioritize.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,251 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Queue                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_queue.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_queue_prioritize                                PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function places the highest priority suspended thread at the   */ | ||||
| /*    front of the suspension list.  All other threads remain in the same */ | ||||
| /*    FIFO suspension order.                                              */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    queue_ptr                         Pointer to queue control block    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_queue_prioritize(TX_QUEUE *queue_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_THREAD       *priority_thread_ptr; | ||||
| TX_THREAD       *head_ptr; | ||||
| UINT            suspended_count; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| UINT            list_changed; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to place message in the queue.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_PRIORITIZE, queue_ptr, queue_ptr -> tx_queue_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_QUEUE_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_QUEUE_PRIORITIZE_INSERT | ||||
|  | ||||
|     /* Pickup the suspended count.  */ | ||||
|     suspended_count =  queue_ptr -> tx_queue_suspended_count; | ||||
|  | ||||
|     /* Determine if there are fewer than 2 suspended threads.  */ | ||||
|     if (suspended_count < ((UINT) 2)) | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|  | ||||
|     /* Determine if there how many threads are suspended on this queue.  */ | ||||
|     else if (suspended_count == ((UINT) 2)) | ||||
|     { | ||||
|  | ||||
|         /* Pickup the head pointer and the next pointer.  */ | ||||
|         head_ptr =  queue_ptr -> tx_queue_suspension_list; | ||||
|         next_thread =  head_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|         /* Determine if the next suspended thread has a higher priority.  */ | ||||
|         if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority)) | ||||
|         { | ||||
|  | ||||
|             /* Yes, move the list head to the next thread.  */ | ||||
|             queue_ptr -> tx_queue_suspension_list =  next_thread; | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Remember the suspension count and head pointer.  */ | ||||
|         head_ptr =   queue_ptr -> tx_queue_suspension_list; | ||||
|  | ||||
|         /* Default the highest priority thread to the thread at the front of the list.  */ | ||||
|         priority_thread_ptr =  head_ptr; | ||||
|  | ||||
|         /* Setup search pointer.  */ | ||||
|         thread_ptr =  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|         /* Disable preemption.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Set the list changed flag to false.  */ | ||||
|         list_changed =  TX_FALSE; | ||||
|  | ||||
|         /* Search through the list to find the highest priority thread.  */ | ||||
|         do | ||||
|         { | ||||
|  | ||||
|             /* Is the current thread higher priority?  */ | ||||
|             if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, remember that this thread is the highest priority.  */ | ||||
|                 priority_thread_ptr =  thread_ptr; | ||||
|             } | ||||
|  | ||||
|             /* Restore interrupts temporarily.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Disable interrupts again.  */ | ||||
|             TX_DISABLE | ||||
|  | ||||
|             /* Determine if any changes to the list have occurred while | ||||
|                interrupts were enabled.  */ | ||||
|  | ||||
|             /* Is the list head the same?  */ | ||||
|             if (head_ptr != queue_ptr -> tx_queue_suspension_list) | ||||
|             { | ||||
|  | ||||
|                 /* The list head has changed, set the list changed flag.  */ | ||||
|                 list_changed =  TX_TRUE; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Is the suspended count the same?  */ | ||||
|                 if (suspended_count != queue_ptr -> tx_queue_suspended_count) | ||||
|                 { | ||||
|  | ||||
|                     /* The list head has changed, set the list changed flag.  */ | ||||
|                     list_changed =  TX_TRUE; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             /* Determine if the list has changed.  */ | ||||
|             if (list_changed == TX_FALSE) | ||||
|             { | ||||
|  | ||||
|                 /* Move the thread pointer to the next thread.  */ | ||||
|                 thread_ptr =  thread_ptr -> tx_thread_suspended_next; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Save the suspension count and head pointer.  */ | ||||
|                 head_ptr =   queue_ptr -> tx_queue_suspension_list; | ||||
|                 suspended_count =  queue_ptr -> tx_queue_suspended_count; | ||||
|  | ||||
|                 /* Default the highest priority thread to the thread at the front of the list.  */ | ||||
|                 priority_thread_ptr =  head_ptr; | ||||
|  | ||||
|                 /* Setup search pointer.  */ | ||||
|                 thread_ptr =  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|                 /* Reset the list changed flag.  */ | ||||
|                 list_changed =  TX_FALSE; | ||||
|             } | ||||
|  | ||||
|         } while (thread_ptr != head_ptr); | ||||
|  | ||||
|         /* Release preemption.  */ | ||||
|         _tx_thread_preempt_disable--; | ||||
|  | ||||
|         /* Now determine if the highest priority thread is at the front | ||||
|            of the list.  */ | ||||
|         if (priority_thread_ptr != head_ptr) | ||||
|         { | ||||
|  | ||||
|             /* No, we need to move the highest priority suspended thread to the | ||||
|                front of the list.  */ | ||||
|  | ||||
|             /* First, remove the highest priority thread by updating the | ||||
|                adjacent suspended threads.  */ | ||||
|             next_thread =                                  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|             previous_thread =                              priority_thread_ptr -> tx_thread_suspended_previous; | ||||
|             next_thread -> tx_thread_suspended_previous =  previous_thread; | ||||
|             previous_thread -> tx_thread_suspended_next =  next_thread; | ||||
|  | ||||
|             /* Now, link the highest priority thread at the front of the list.  */ | ||||
|             previous_thread =                                      head_ptr -> tx_thread_suspended_previous; | ||||
|             priority_thread_ptr -> tx_thread_suspended_next =      head_ptr; | ||||
|             priority_thread_ptr -> tx_thread_suspended_previous =  previous_thread; | ||||
|             previous_thread -> tx_thread_suspended_next =          priority_thread_ptr; | ||||
|             head_ptr -> tx_thread_suspended_previous =             priority_thread_ptr; | ||||
|  | ||||
|             /* Move the list head pointer to the highest priority suspended thread.  */ | ||||
|             queue_ptr -> tx_queue_suspension_list =  priority_thread_ptr; | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Check for preemption.  */ | ||||
|         _tx_thread_system_preempt_check(); | ||||
|     } | ||||
|  | ||||
|     /* Return successful status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										488
									
								
								Middlewares/ST/threadx/common/src/tx_queue_receive.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										488
									
								
								Middlewares/ST/threadx/common/src/tx_queue_receive.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,488 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Queue                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_queue.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_queue_receive                                   PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function receives a message from the specified queue. If there */ | ||||
| /*    are no messages in the queue, this function waits according to the  */ | ||||
| /*    option specified.                                                   */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    queue_ptr                         Pointer to queue control block    */ | ||||
| /*    destination_ptr                   Pointer to message destination    */ | ||||
| /*                                        **** MUST BE LARGE ENOUGH TO    */ | ||||
| /*                                             HOLD MESSAGE ****          */ | ||||
| /*    wait_option                       Suspension option                 */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread routine             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*    _tx_thread_system_suspend         Suspend thread routine            */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| ULONG           *source; | ||||
| ULONG           *destination; | ||||
| UINT            size; | ||||
| UINT            suspended_count; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| UINT            status; | ||||
|  | ||||
|  | ||||
|     /* Default the status to TX_SUCCESS.  */ | ||||
|     status =  TX_SUCCESS; | ||||
|  | ||||
|     /* Disable interrupts to receive message from queue.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Increment the total messages received counter.  */ | ||||
|     _tx_queue_performance__messages_received_count++; | ||||
|  | ||||
|     /* Increment the number of messages received from this queue.  */ | ||||
|     queue_ptr -> tx_queue_performance_messages_received_count++; | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_RECEIVE, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(destination_ptr), wait_option, queue_ptr -> tx_queue_enqueued, TX_TRACE_QUEUE_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_QUEUE_RECEIVE_INSERT | ||||
|  | ||||
|     /* Pickup the thread suspension count.  */ | ||||
|     suspended_count =  queue_ptr -> tx_queue_suspended_count; | ||||
|  | ||||
|     /* Determine if there is anything in the queue.  */ | ||||
|     if (queue_ptr -> tx_queue_enqueued != TX_NO_MESSAGES) | ||||
|     { | ||||
|  | ||||
|         /* Determine if there are any suspensions.  */ | ||||
|         if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|         { | ||||
|  | ||||
|             /* There is a message waiting in the queue and there are no suspensi.  */ | ||||
|  | ||||
|             /* Setup source and destination pointers.  */ | ||||
|             source =       queue_ptr -> tx_queue_read; | ||||
|             destination =  TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr); | ||||
|             size =         queue_ptr -> tx_queue_message_size; | ||||
|  | ||||
|             /* Copy message. Note that the source and destination pointers are | ||||
|                incremented by the macro.  */ | ||||
|             TX_QUEUE_MESSAGE_COPY(source, destination, size) | ||||
|  | ||||
|             /* Determine if we are at the end.  */ | ||||
|             if (source == queue_ptr -> tx_queue_end) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, wrap around to the beginning.  */ | ||||
|                 source =  queue_ptr -> tx_queue_start; | ||||
|             } | ||||
|  | ||||
|             /* Setup the queue read pointer.   */ | ||||
|             queue_ptr -> tx_queue_read =  source; | ||||
|  | ||||
|             /* Increase the amount of available storage.  */ | ||||
|             queue_ptr -> tx_queue_available_storage++; | ||||
|  | ||||
|             /* Decrease the enqueued count.  */ | ||||
|             queue_ptr -> tx_queue_enqueued--; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* At this point we know the queue is full.  */ | ||||
|  | ||||
|             /* Pickup thread suspension list head pointer.  */ | ||||
|             thread_ptr =  queue_ptr -> tx_queue_suspension_list; | ||||
|  | ||||
|             /* Now determine if there is a queue front suspension active.   */ | ||||
|  | ||||
|             /* Is the front suspension flag set?  */ | ||||
|             if (thread_ptr -> tx_thread_suspend_option == TX_TRUE) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, a queue front suspension is present.  */ | ||||
|  | ||||
|                 /* Return the message associated with this suspension.  */ | ||||
|  | ||||
|                 /* Setup source and destination pointers.  */ | ||||
|                 source =       TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info); | ||||
|                 destination =  TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr); | ||||
|                 size =         queue_ptr -> tx_queue_message_size; | ||||
|  | ||||
|                 /* Copy message. Note that the source and destination pointers are | ||||
|                    incremented by the macro.  */ | ||||
|                 TX_QUEUE_MESSAGE_COPY(source, destination, size) | ||||
|  | ||||
|                 /* Message is now in the caller's destination. See if this is the only suspended thread | ||||
|                    on the list.  */ | ||||
|                 suspended_count--; | ||||
|                 if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|                 { | ||||
|  | ||||
|                     /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|                     /* Update the head pointer.  */ | ||||
|                     queue_ptr -> tx_queue_suspension_list =  TX_NULL; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* At least one more thread is on the same expiration list.  */ | ||||
|  | ||||
|                     /* Update the list head pointer.  */ | ||||
|                     next_thread =                            thread_ptr -> tx_thread_suspended_next; | ||||
|                     queue_ptr -> tx_queue_suspension_list =  next_thread; | ||||
|  | ||||
|                     /* Update the links of the adjacent threads.  */ | ||||
|                     previous_thread =                              thread_ptr -> tx_thread_suspended_previous; | ||||
|                     next_thread -> tx_thread_suspended_previous =  previous_thread; | ||||
|                     previous_thread -> tx_thread_suspended_next =  next_thread; | ||||
|                 } | ||||
|  | ||||
|                 /* Decrement the suspension count.  */ | ||||
|                 queue_ptr -> tx_queue_suspended_count =  suspended_count; | ||||
|  | ||||
|                 /* Prepare for resumption of the first thread.  */ | ||||
|  | ||||
|                 /* Clear cleanup routine to avoid timeout.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|                 /* Put return status into the thread control block.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                 /* Resume the thread!  */ | ||||
|                 _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
| #else | ||||
|  | ||||
|                 /* Temporarily disable preemption.  */ | ||||
|                 _tx_thread_preempt_disable++; | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Resume thread.  */ | ||||
|                 _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* At this point, we know that the queue is full and there | ||||
|                    are one or more threads suspended trying to send another | ||||
|                    message to this queue.  */ | ||||
|  | ||||
|                 /* Setup source and destination pointers.  */ | ||||
|                 source =       queue_ptr -> tx_queue_read; | ||||
|                 destination =  TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr); | ||||
|                 size =         queue_ptr -> tx_queue_message_size; | ||||
|  | ||||
|                 /* Copy message. Note that the source and destination pointers are | ||||
|                    incremented by the macro.  */ | ||||
|                 TX_QUEUE_MESSAGE_COPY(source, destination, size) | ||||
|  | ||||
|                 /* Determine if we are at the end.  */ | ||||
|                 if (source == queue_ptr -> tx_queue_end) | ||||
|                 { | ||||
|  | ||||
|                     /* Yes, wrap around to the beginning.  */ | ||||
|                     source =  queue_ptr -> tx_queue_start; | ||||
|                 } | ||||
|  | ||||
|                 /* Setup the queue read pointer.   */ | ||||
|                 queue_ptr -> tx_queue_read =  source; | ||||
|  | ||||
|                 /* Disable preemption.  */ | ||||
|                 _tx_thread_preempt_disable++; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Interrupts are enabled briefly here to keep the interrupt | ||||
|                    lockout time deterministic.  */ | ||||
|  | ||||
|                 /* Disable interrupts again.  */ | ||||
|                 TX_DISABLE | ||||
| #endif | ||||
|  | ||||
|                 /* Decrement the preemption disable variable.  */ | ||||
|                 _tx_thread_preempt_disable--; | ||||
|  | ||||
|                 /* Setup source and destination pointers.  */ | ||||
|                 source =       TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info); | ||||
|                 destination =  queue_ptr -> tx_queue_write; | ||||
|                 size =         queue_ptr -> tx_queue_message_size; | ||||
|  | ||||
|                 /* Copy message. Note that the source and destination pointers are | ||||
|                    incremented by the macro.  */ | ||||
|                 TX_QUEUE_MESSAGE_COPY(source, destination, size) | ||||
|  | ||||
|                 /* Determine if we are at the end.  */ | ||||
|                 if (destination == queue_ptr -> tx_queue_end) | ||||
|                 { | ||||
|  | ||||
|                     /* Yes, wrap around to the beginning.  */ | ||||
|                     destination =  queue_ptr -> tx_queue_start; | ||||
|                 } | ||||
|  | ||||
|                 /* Adjust the write pointer.  */ | ||||
|                 queue_ptr -> tx_queue_write =  destination; | ||||
|  | ||||
|                 /* Pickup thread pointer.  */ | ||||
|                 thread_ptr =  queue_ptr -> tx_queue_suspension_list; | ||||
|  | ||||
|                 /* Message is now in the queue.  See if this is the only suspended thread | ||||
|                    on the list.  */ | ||||
|                 suspended_count--; | ||||
|                 if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|                 { | ||||
|  | ||||
|                   /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|                     /* Update the head pointer.  */ | ||||
|                     queue_ptr -> tx_queue_suspension_list =  TX_NULL; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* At least one more thread is on the same expiration list.  */ | ||||
|  | ||||
|                     /* Update the list head pointer.  */ | ||||
|                     next_thread =                            thread_ptr -> tx_thread_suspended_next; | ||||
|                     queue_ptr -> tx_queue_suspension_list =  next_thread; | ||||
|  | ||||
|                     /* Update the links of the adjacent threads.  */ | ||||
|                     previous_thread =                               thread_ptr -> tx_thread_suspended_previous; | ||||
|                     next_thread -> tx_thread_suspended_previous =   previous_thread; | ||||
|                     previous_thread -> tx_thread_suspended_next =   next_thread; | ||||
|                 } | ||||
|  | ||||
|                 /* Decrement the suspension count.  */ | ||||
|                 queue_ptr -> tx_queue_suspended_count =  suspended_count; | ||||
|  | ||||
|                 /* Prepare for resumption of the first thread.  */ | ||||
|  | ||||
|                 /* Clear cleanup routine to avoid timeout.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|                 /* Put return status into the thread control block.  */ | ||||
|                 thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                 /* Resume the thread!  */ | ||||
|                 _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
| #else | ||||
|  | ||||
|                 /* Temporarily disable preemption.  */ | ||||
|                 _tx_thread_preempt_disable++; | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Resume thread.  */ | ||||
|                 _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Determine if the request specifies suspension.  */ | ||||
|     else if (wait_option != TX_NO_WAIT) | ||||
|     { | ||||
|  | ||||
|         /* Determine if the preempt disable flag is non-zero.  */ | ||||
|         if (_tx_thread_preempt_disable != ((UINT) 0)) | ||||
|         { | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion.  */ | ||||
|             status =  TX_QUEUE_EMPTY; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Prepare for suspension of this thread.  */ | ||||
|  | ||||
| #ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|             /* Increment the total queue empty suspensions counter.  */ | ||||
|             _tx_queue_performance_empty_suspension_count++; | ||||
|  | ||||
|             /* Increment the number of empty suspensions on this queue.  */ | ||||
|             queue_ptr -> tx_queue_performance_empty_suspension_count++; | ||||
| #endif | ||||
|  | ||||
|             /* Pickup thread pointer.  */ | ||||
|             TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
|             /* Setup cleanup routine pointer.  */ | ||||
|             thread_ptr -> tx_thread_suspend_cleanup =  &(_tx_queue_cleanup); | ||||
|  | ||||
|             /* Setup cleanup information, i.e. this queue control | ||||
|                block and the source pointer.  */ | ||||
|             thread_ptr -> tx_thread_suspend_control_block =    (VOID *) queue_ptr; | ||||
|             thread_ptr -> tx_thread_additional_suspend_info =  (VOID *) destination_ptr; | ||||
|             thread_ptr -> tx_thread_suspend_option =           TX_FALSE; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Increment the suspension sequence number, which is used to identify | ||||
|                this suspension event.  */ | ||||
|             thread_ptr -> tx_thread_suspension_sequence++; | ||||
| #endif | ||||
|  | ||||
|             /* Setup suspension list.  */ | ||||
|             if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|             { | ||||
|  | ||||
|                 /* No other threads are suspended.  Setup the head pointer and | ||||
|                    just setup this threads pointers to itself.  */ | ||||
|                 queue_ptr -> tx_queue_suspension_list =         thread_ptr; | ||||
|                 thread_ptr -> tx_thread_suspended_next =        thread_ptr; | ||||
|                 thread_ptr -> tx_thread_suspended_previous =    thread_ptr; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* This list is not NULL, add current thread to the end. */ | ||||
|                 next_thread =                                   queue_ptr -> tx_queue_suspension_list; | ||||
|                 thread_ptr -> tx_thread_suspended_next =        next_thread; | ||||
|                 previous_thread =                               next_thread -> tx_thread_suspended_previous; | ||||
|                 thread_ptr -> tx_thread_suspended_previous =    previous_thread; | ||||
|                 previous_thread -> tx_thread_suspended_next =   thread_ptr; | ||||
|                 next_thread -> tx_thread_suspended_previous =   thread_ptr; | ||||
|             } | ||||
|  | ||||
|             /* Increment the suspended thread count.  */ | ||||
|             queue_ptr -> tx_queue_suspended_count =  suspended_count + ((UINT) 1); | ||||
|  | ||||
|             /* Set the state to suspended.  */ | ||||
|             thread_ptr -> tx_thread_state =    TX_QUEUE_SUSP; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Call actual non-interruptable thread suspension routine.  */ | ||||
|             _tx_thread_system_ni_suspend(thread_ptr, wait_option); | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #else | ||||
|  | ||||
|             /* Set the suspending flag.  */ | ||||
|             thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|             /* Setup the timeout period.  */ | ||||
|             thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  wait_option; | ||||
|  | ||||
|             /* Temporarily disable preemption.  */ | ||||
|             _tx_thread_preempt_disable++; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Call actual thread suspension routine.  */ | ||||
|             _tx_thread_system_suspend(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|             /* Return the completion status.  */ | ||||
|             status =  thread_ptr -> tx_thread_suspend_status; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Immediate return, return error completion.  */ | ||||
|         status =  TX_QUEUE_EMPTY; | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										428
									
								
								Middlewares/ST/threadx/common/src/tx_queue_send.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										428
									
								
								Middlewares/ST/threadx/common/src/tx_queue_send.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,428 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Queue                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_queue.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_queue_send                                      PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function places a message into the specified queue.  If there  */ | ||||
| /*    is no room in the queue, this function waits according to the       */ | ||||
| /*    option specified.                                                   */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    queue_ptr                         Pointer to queue control block    */ | ||||
| /*    source_ptr                        Pointer to message source         */ | ||||
| /*    wait_option                       Suspension option                 */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread routine             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*    _tx_thread_system_suspend         Suspend thread routine            */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_queue_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| ULONG           *source; | ||||
| ULONG           *destination; | ||||
| UINT            size; | ||||
| UINT            suspended_count; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| UINT            status; | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
| VOID            (*queue_send_notify)(struct TX_QUEUE_STRUCT *notify_queue_ptr); | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     /* Default the status to TX_SUCCESS.  */ | ||||
|     status =  TX_SUCCESS; | ||||
|  | ||||
|     /* Disable interrupts to place message in the queue.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Increment the total messages sent counter.  */ | ||||
|     _tx_queue_performance_messages_sent_count++; | ||||
|  | ||||
|     /* Increment the number of messages sent to this queue.  */ | ||||
|     queue_ptr -> tx_queue_performance_messages_sent_count++; | ||||
| #endif | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_SEND, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(source_ptr), wait_option, queue_ptr -> tx_queue_enqueued, TX_TRACE_QUEUE_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_QUEUE_SEND_INSERT | ||||
|  | ||||
|     /* Pickup the thread suspension count.  */ | ||||
|     suspended_count =  queue_ptr -> tx_queue_suspended_count; | ||||
|  | ||||
|     /* Determine if there is room in the queue.  */ | ||||
|     if (queue_ptr -> tx_queue_available_storage != TX_NO_MESSAGES) | ||||
|     { | ||||
|  | ||||
|         /* There is room for the message in the queue.  */ | ||||
|  | ||||
|         /* Determine if there are suspended on this queue.  */ | ||||
|         if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|         { | ||||
|  | ||||
|             /* No suspended threads, simply place the message in the queue.  */ | ||||
|  | ||||
|             /* Reduce the amount of available storage.  */ | ||||
|             queue_ptr -> tx_queue_available_storage--; | ||||
|  | ||||
|             /* Increase the enqueued count.  */ | ||||
|             queue_ptr -> tx_queue_enqueued++; | ||||
|  | ||||
|             /* Setup source and destination pointers.  */ | ||||
|             source =       TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr); | ||||
|             destination =  queue_ptr -> tx_queue_write; | ||||
|             size =         queue_ptr -> tx_queue_message_size; | ||||
|  | ||||
|             /* Copy message. Note that the source and destination pointers are | ||||
|                incremented by the macro.  */ | ||||
|             TX_QUEUE_MESSAGE_COPY(source, destination, size) | ||||
|  | ||||
|             /* Determine if we are at the end.  */ | ||||
|             if (destination == queue_ptr -> tx_queue_end) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, wrap around to the beginning.  */ | ||||
|                 destination =  queue_ptr -> tx_queue_start; | ||||
|             } | ||||
|  | ||||
|             /* Adjust the write pointer.  */ | ||||
|             queue_ptr -> tx_queue_write =  destination; | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Pickup the notify callback routine for this queue.  */ | ||||
|             queue_send_notify =  queue_ptr -> tx_queue_send_notify; | ||||
| #endif | ||||
|  | ||||
|             /* No thread suspended, just return to caller.  */ | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Determine if a notify callback is required.  */ | ||||
|             if (queue_send_notify != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Call application queue send notification.  */ | ||||
|                 (queue_send_notify)(queue_ptr); | ||||
|             } | ||||
| #endif | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* There is a thread suspended on an empty queue. Simply | ||||
|                copy the message to the suspended thread's destination | ||||
|                pointer.  */ | ||||
|  | ||||
|             /* Pickup the head of the suspension list.  */ | ||||
|             thread_ptr =  queue_ptr -> tx_queue_suspension_list; | ||||
|  | ||||
|             /* See if this is the only suspended thread on the list.  */ | ||||
|             suspended_count--; | ||||
|             if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|                 /* Update the head pointer.  */ | ||||
|                 queue_ptr -> tx_queue_suspension_list =  TX_NULL; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* At least one more thread is on the same expiration list.  */ | ||||
|  | ||||
|                 /* Update the list head pointer.  */ | ||||
|                 queue_ptr -> tx_queue_suspension_list =  thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|                 /* Update the links of the adjacent threads.  */ | ||||
|                 next_thread =                            thread_ptr -> tx_thread_suspended_next; | ||||
|                 queue_ptr -> tx_queue_suspension_list =  next_thread; | ||||
|  | ||||
|                 /* Update the links of the adjacent threads.  */ | ||||
|                 previous_thread =                               thread_ptr -> tx_thread_suspended_previous; | ||||
|                 next_thread -> tx_thread_suspended_previous =   previous_thread; | ||||
|                 previous_thread -> tx_thread_suspended_next =   next_thread; | ||||
|             } | ||||
|  | ||||
|             /* Decrement the suspension count.  */ | ||||
|             queue_ptr -> tx_queue_suspended_count =  suspended_count; | ||||
|  | ||||
|             /* Prepare for resumption of the thread.  */ | ||||
|  | ||||
|             /* Clear cleanup routine to avoid timeout.  */ | ||||
|             thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|             /* Setup source and destination pointers.  */ | ||||
|             source =       TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr); | ||||
|             destination =  TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info); | ||||
|             size =         queue_ptr -> tx_queue_message_size; | ||||
|  | ||||
|             /* Copy message. Note that the source and destination pointers are | ||||
|                incremented by the macro.  */ | ||||
|             TX_QUEUE_MESSAGE_COPY(source, destination, size) | ||||
|  | ||||
|             /* Put return status into the thread control block.  */ | ||||
|             thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS; | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Pickup the notify callback routine for this queue.  */ | ||||
|             queue_send_notify =  queue_ptr -> tx_queue_send_notify; | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Resume the thread!  */ | ||||
|             _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #else | ||||
|  | ||||
|             /* Temporarily disable preemption.  */ | ||||
|             _tx_thread_preempt_disable++; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Resume thread.  */ | ||||
|             _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Determine if a notify callback is required.  */ | ||||
|             if (queue_send_notify != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Call application queue send notification.  */ | ||||
|                 (queue_send_notify)(queue_ptr); | ||||
|             } | ||||
| #endif | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* At this point, the queue is full. Determine if suspension is requested.  */ | ||||
|     else if (wait_option != TX_NO_WAIT) | ||||
|     { | ||||
|  | ||||
|         /* Determine if the preempt disable flag is non-zero.  */ | ||||
|         if (_tx_thread_preempt_disable != ((UINT) 0)) | ||||
|         { | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion.  */ | ||||
|             status =  TX_QUEUE_FULL; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Yes, prepare for suspension of this thread.  */ | ||||
|  | ||||
| #ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|             /* Increment the total number of queue full suspensions.  */ | ||||
|             _tx_queue_performance_full_suspension_count++; | ||||
|  | ||||
|             /* Increment the number of full suspensions on this queue.  */ | ||||
|             queue_ptr -> tx_queue_performance_full_suspension_count++; | ||||
| #endif | ||||
|  | ||||
|             /* Pickup thread pointer.  */ | ||||
|             TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
|             /* Setup cleanup routine pointer.  */ | ||||
|             thread_ptr -> tx_thread_suspend_cleanup =  &(_tx_queue_cleanup); | ||||
|  | ||||
|             /* Setup cleanup information, i.e. this queue control | ||||
|                block and the source pointer.  */ | ||||
|             thread_ptr -> tx_thread_suspend_control_block =    (VOID *) queue_ptr; | ||||
|             thread_ptr -> tx_thread_additional_suspend_info =  (VOID *) source_ptr; | ||||
|             thread_ptr -> tx_thread_suspend_option =           TX_FALSE; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Increment the suspension sequence number, which is used to identify | ||||
|                this suspension event.  */ | ||||
|             thread_ptr -> tx_thread_suspension_sequence++; | ||||
| #endif | ||||
|  | ||||
|             /* Setup suspension list.  */ | ||||
|             if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|             { | ||||
|  | ||||
|                 /* No other threads are suspended.  Setup the head pointer and | ||||
|                    just setup this threads pointers to itself.  */ | ||||
|                 queue_ptr -> tx_queue_suspension_list =         thread_ptr; | ||||
|                 thread_ptr -> tx_thread_suspended_next =        thread_ptr; | ||||
|                 thread_ptr -> tx_thread_suspended_previous =    thread_ptr; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* This list is not NULL, add current thread to the end. */ | ||||
|                 next_thread =                                   queue_ptr -> tx_queue_suspension_list; | ||||
|                 thread_ptr -> tx_thread_suspended_next =        next_thread; | ||||
|                 previous_thread =                               next_thread -> tx_thread_suspended_previous; | ||||
|                 thread_ptr -> tx_thread_suspended_previous =    previous_thread; | ||||
|                 previous_thread -> tx_thread_suspended_next =   thread_ptr; | ||||
|                 next_thread -> tx_thread_suspended_previous =   thread_ptr; | ||||
|             } | ||||
|  | ||||
|             /* Increment the suspended thread count.  */ | ||||
|             queue_ptr -> tx_queue_suspended_count =  suspended_count + ((UINT) 1); | ||||
|  | ||||
|             /* Set the state to suspended.  */ | ||||
|             thread_ptr -> tx_thread_state =    TX_QUEUE_SUSP; | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Pickup the notify callback routine for this queue.  */ | ||||
|             queue_send_notify =  queue_ptr -> tx_queue_send_notify; | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Call actual non-interruptable thread suspension routine.  */ | ||||
|             _tx_thread_system_ni_suspend(thread_ptr, wait_option); | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #else | ||||
|  | ||||
|             /* Set the suspending flag.  */ | ||||
|             thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|             /* Setup the timeout period.  */ | ||||
|             thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  wait_option; | ||||
|  | ||||
|             /* Temporarily disable preemption.  */ | ||||
|             _tx_thread_preempt_disable++; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Call actual thread suspension routine.  */ | ||||
|             _tx_thread_system_suspend(thread_ptr); | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Determine if a notify callback is required.  */ | ||||
|             if (thread_ptr -> tx_thread_suspend_status == TX_SUCCESS) | ||||
|             { | ||||
|  | ||||
|                 /* Determine if there is a notify callback.  */ | ||||
|                 if (queue_send_notify != TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     /* Call application queue send notification.  */ | ||||
|                     (queue_send_notify)(queue_ptr); | ||||
|                 } | ||||
|             } | ||||
| #endif | ||||
|  | ||||
|             /* Return the completion status.  */ | ||||
|             status =  thread_ptr -> tx_thread_suspend_status; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Otherwise, just return a queue full error message to the caller.  */ | ||||
|  | ||||
| #ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|         /* Increment the number of full non-suspensions on this queue.  */ | ||||
|         queue_ptr -> tx_queue_performance_full_error_count++; | ||||
|  | ||||
|         /* Increment the total number of full non-suspensions.  */ | ||||
|         _tx_queue_performance_full_error_count++; | ||||
| #endif | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Return error completion.  */ | ||||
|         status =  TX_QUEUE_FULL; | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										109
									
								
								Middlewares/ST/threadx/common/src/tx_queue_send_notify.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								Middlewares/ST/threadx/common/src/tx_queue_send_notify.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Queue                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_queue.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_queue_send_notify                               PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function registers an application callback function that is    */ | ||||
| /*    called whenever a messages is sent to this queue.                   */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    queue_ptr                             Pointer to queue control block*/ | ||||
| /*    queue_send_notify                     Application callback function */ | ||||
| /*                                            (TX_NULL disables notify)   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Completion status             */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_queue_send_notify(TX_QUEUE *queue_ptr, VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)) | ||||
| { | ||||
|  | ||||
| #ifdef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|     TX_QUEUE_NOT_USED(queue_ptr); | ||||
|     TX_QUEUE_SEND_NOTIFY_NOT_USED(queue_send_notify); | ||||
|  | ||||
|     /* Feature is not enabled, return error.  */ | ||||
|     return(TX_FEATURE_NOT_ENABLED); | ||||
| #else | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Make entry in event log.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_SEND_NOTIFY, queue_ptr, 0, 0, 0, TX_TRACE_QUEUE_EVENTS) | ||||
|  | ||||
|     /* Make entry in event log.  */ | ||||
|     TX_EL_QUEUE_SEND_NOTIFY_INSERT | ||||
|  | ||||
|     /* Setup queue send notification callback function.  */ | ||||
|     queue_ptr -> tx_queue_send_notify =  queue_send_notify; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return success to caller.  */ | ||||
|     return(TX_SUCCESS); | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										245
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_ceiling_put.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_ceiling_put.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,245 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Semaphore                                                           */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_semaphore.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_semaphore_ceiling_put                           PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function puts an instance into the specified counting          */ | ||||
| /*    semaphore up to the specified semaphore ceiling.                    */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    semaphore_ptr                         Pointer to semaphore          */ | ||||
| /*    ceiling                               Maximum value of semaphore    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Completion status             */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume              Resume thread service         */ | ||||
| /*    _tx_thread_system_ni_resume           Non-interruptable resume      */ | ||||
| /*                                            thread                      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
| VOID            (*semaphore_put_notify)(struct TX_SEMAPHORE_STRUCT *notify_semaphore_ptr); | ||||
| #endif | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| UINT            suspended_count; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| UINT            status; | ||||
|  | ||||
|  | ||||
|     /* Default the status to TX_SUCCESS.  */ | ||||
|     status =  TX_SUCCESS; | ||||
|  | ||||
|     /* Disable interrupts to put an instance back to the semaphore.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Increment the total semaphore put counter.  */ | ||||
|     _tx_semaphore_performance_put_count++; | ||||
|  | ||||
|     /* Increment the number of puts on this semaphore.  */ | ||||
|     semaphore_ptr -> tx_semaphore_performance_put_count++; | ||||
| #endif | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_CEILING_PUT, semaphore_ptr, semaphore_ptr -> tx_semaphore_count, semaphore_ptr -> tx_semaphore_suspended_count, ceiling, TX_TRACE_SEMAPHORE_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_SEMAPHORE_CEILING_PUT_INSERT | ||||
|  | ||||
|     /* Pickup the number of suspended threads.  */ | ||||
|     suspended_count =  semaphore_ptr -> tx_semaphore_suspended_count; | ||||
|  | ||||
|     /* Determine if there are any threads suspended on the semaphore.  */ | ||||
|     if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|     { | ||||
|  | ||||
|         /* Determine if the ceiling has been exceeded.  */ | ||||
|         if (semaphore_ptr -> tx_semaphore_count >= ceiling) | ||||
|         { | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Return an error.  */ | ||||
|             status =  TX_CEILING_EXCEEDED; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Increment the semaphore count.  */ | ||||
|             semaphore_ptr -> tx_semaphore_count++; | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Pickup the application notify function.  */ | ||||
|             semaphore_put_notify =  semaphore_ptr -> tx_semaphore_put_notify; | ||||
| #endif | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Determine if notification is required.  */ | ||||
|             if (semaphore_put_notify != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, call the appropriate notify callback function.  */ | ||||
|                 (semaphore_put_notify)(semaphore_ptr); | ||||
|             } | ||||
| #endif | ||||
|  | ||||
|             /* Return successful completion status.  */ | ||||
|             status =  TX_SUCCESS; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Remove the suspended thread from the list.  */ | ||||
|  | ||||
|         /* Pickup the pointer to the first suspended thread.  */ | ||||
|         thread_ptr =  semaphore_ptr -> tx_semaphore_suspension_list; | ||||
|  | ||||
|         /* See if this is the only suspended thread on the list.  */ | ||||
|         suspended_count--; | ||||
|         if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|         { | ||||
|  | ||||
|             /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|             /* Update the head pointer.  */ | ||||
|             semaphore_ptr -> tx_semaphore_suspension_list =  TX_NULL; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* At least one more thread is on the same expiration list.  */ | ||||
|  | ||||
|             /* Update the list head pointer.  */ | ||||
|             next_thread =                                     thread_ptr -> tx_thread_suspended_next; | ||||
|             semaphore_ptr -> tx_semaphore_suspension_list =   next_thread; | ||||
|  | ||||
|             /* Update the links of the adjacent threads.  */ | ||||
|             previous_thread =                               thread_ptr -> tx_thread_suspended_previous; | ||||
|             next_thread -> tx_thread_suspended_previous =   previous_thread; | ||||
|             previous_thread -> tx_thread_suspended_next =   next_thread; | ||||
|         } | ||||
|  | ||||
|         /* Decrement the suspension count.  */ | ||||
|         semaphore_ptr -> tx_semaphore_suspended_count =  suspended_count; | ||||
|  | ||||
|         /* Prepare for resumption of the first thread.  */ | ||||
|  | ||||
|         /* Clear cleanup routine to avoid timeout.  */ | ||||
|         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|         /* Put return status into the thread control block.  */ | ||||
|         thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS; | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|         /* Pickup the application notify function.  */ | ||||
|         semaphore_put_notify =  semaphore_ptr -> tx_semaphore_put_notify; | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Resume the thread!  */ | ||||
|         _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #else | ||||
|  | ||||
|         /* Temporarily disable preemption.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Resume thread.  */ | ||||
|         _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|         /* Determine if notification is required.  */ | ||||
|         if (semaphore_put_notify != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Yes, call the appropriate notify callback function.  */ | ||||
|             (semaphore_put_notify)(semaphore_ptr); | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     /* Return successful completion.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										217
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_cleanup.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_cleanup.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,217 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Semaphore                                                           */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_semaphore.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_semaphore_cleanup                               PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function processes semaphore timeout and thread terminate      */ | ||||
| /*    actions that require the semaphore data structures to be cleaned    */ | ||||
| /*    up.                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                        Pointer to suspended thread's     */ | ||||
| /*                                        control block                   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_timeout                Thread timeout processing         */ | ||||
| /*    _tx_thread_terminate              Thread terminate processing       */ | ||||
| /*    _tx_thread_wait_abort             Thread wait abort processing      */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_semaphore_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence) | ||||
| { | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
| #endif | ||||
|  | ||||
| TX_SEMAPHORE        *semaphore_ptr; | ||||
| UINT                suspended_count; | ||||
| TX_THREAD           *next_thread; | ||||
| TX_THREAD           *previous_thread; | ||||
|  | ||||
|  | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|     /* Disable interrupts to remove the suspended thread from the semaphore.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Determine if the cleanup is still required.  */ | ||||
|     if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_semaphore_cleanup)) | ||||
|     { | ||||
|  | ||||
|         /* Check for valid suspension sequence.  */ | ||||
|         if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence) | ||||
|         { | ||||
|  | ||||
|             /* Setup pointer to semaphore control block.  */ | ||||
|             semaphore_ptr =  TX_VOID_TO_SEMAPHORE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); | ||||
|  | ||||
|             /* Check for a NULL semaphore pointer.  */ | ||||
|             if (semaphore_ptr != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Check for a valid semaphore ID.  */ | ||||
|                 if (semaphore_ptr -> tx_semaphore_id == TX_SEMAPHORE_ID) | ||||
|                 { | ||||
|  | ||||
|                     /* Determine if there are any thread suspensions.  */ | ||||
|                     if (semaphore_ptr -> tx_semaphore_suspended_count != TX_NO_SUSPENSIONS) | ||||
|                     { | ||||
| #else | ||||
|  | ||||
|                         /* Setup pointer to semaphore control block.  */ | ||||
|                         semaphore_ptr =  TX_VOID_TO_SEMAPHORE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); | ||||
| #endif | ||||
|  | ||||
|                         /* Yes, we still have thread suspension!  */ | ||||
|  | ||||
|                         /* Clear the suspension cleanup flag.  */ | ||||
|                         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|                         /* Decrement the suspended count.  */ | ||||
|                         semaphore_ptr -> tx_semaphore_suspended_count--; | ||||
|  | ||||
|                         /* Pickup the suspended count.  */ | ||||
|                         suspended_count =  semaphore_ptr -> tx_semaphore_suspended_count; | ||||
|  | ||||
|                         /* Remove the suspended thread from the list.  */ | ||||
|  | ||||
|                         /* See if this is the only suspended thread on the list.  */ | ||||
|                         if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|                         { | ||||
|  | ||||
|                             /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|                             /* Update the head pointer.  */ | ||||
|                             semaphore_ptr -> tx_semaphore_suspension_list =  TX_NULL; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* At least one more thread is on the same suspension list.  */ | ||||
|  | ||||
|                             /* Update the links of the adjacent threads.  */ | ||||
|                             next_thread =                                   thread_ptr -> tx_thread_suspended_next; | ||||
|                             previous_thread =                               thread_ptr -> tx_thread_suspended_previous; | ||||
|                             next_thread -> tx_thread_suspended_previous =   previous_thread; | ||||
|                             previous_thread -> tx_thread_suspended_next =   next_thread; | ||||
|  | ||||
|                             /* Determine if we need to update the head pointer.  */ | ||||
|                             if (semaphore_ptr -> tx_semaphore_suspension_list == thread_ptr) | ||||
|                             { | ||||
|  | ||||
|                                 /* Update the list head pointer.  */ | ||||
|                                 semaphore_ptr -> tx_semaphore_suspension_list =   next_thread; | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         /* Now we need to determine if this cleanup is from a terminate, timeout, | ||||
|                            or from a wait abort.  */ | ||||
|                         if (thread_ptr -> tx_thread_state == TX_SEMAPHORE_SUSP) | ||||
|                         { | ||||
|  | ||||
|                             /* Timeout condition and the thread is still suspended on the semaphore. | ||||
|                                Setup return error status and resume the thread.  */ | ||||
|  | ||||
| #ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                             /* Increment the total timeouts counter.  */ | ||||
|                             _tx_semaphore_performance_timeout_count++; | ||||
|  | ||||
|                             /* Increment the number of timeouts on this semaphore.  */ | ||||
|                             semaphore_ptr -> tx_semaphore_performance_timeout_count++; | ||||
| #endif | ||||
|  | ||||
|                             /* Setup return status.  */ | ||||
|                             thread_ptr -> tx_thread_suspend_status =  TX_NO_INSTANCE; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                             /* Resume the thread!  */ | ||||
|                             _tx_thread_system_ni_resume(thread_ptr); | ||||
| #else | ||||
|  | ||||
|                             /* Temporarily disable preemption.  */ | ||||
|                             _tx_thread_preempt_disable++; | ||||
|  | ||||
|                             /* Restore interrupts.  */ | ||||
|                             TX_RESTORE | ||||
|  | ||||
|                             /* Resume the thread!  */ | ||||
|                             _tx_thread_system_resume(thread_ptr); | ||||
|  | ||||
|                             /* Disable interrupts.  */ | ||||
|                             TX_DISABLE | ||||
| #endif | ||||
|                       } | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										144
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_create.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_create.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Semaphore                                                           */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_semaphore.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_semaphore_create                                PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function creates a counting semaphore with the initial count   */ | ||||
| /*    specified in this call.                                             */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    semaphore_ptr                     Pointer to semaphore control block*/ | ||||
| /*    name_ptr                          Pointer to semaphore name         */ | ||||
| /*    initial_count                     Initial semaphore count           */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_SEMAPHORE    *next_semaphore; | ||||
| TX_SEMAPHORE    *previous_semaphore; | ||||
|  | ||||
|  | ||||
|     /* Initialize semaphore control block to all zeros.  */ | ||||
|     TX_MEMSET(semaphore_ptr, 0, (sizeof(TX_SEMAPHORE))); | ||||
|  | ||||
|     /* Setup the basic semaphore fields.  */ | ||||
|     semaphore_ptr -> tx_semaphore_name =             name_ptr; | ||||
|     semaphore_ptr -> tx_semaphore_count =            initial_count; | ||||
|  | ||||
|     /* Disable interrupts to place the semaphore on the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Setup the semaphore ID to make it valid.  */ | ||||
|     semaphore_ptr -> tx_semaphore_id =  TX_SEMAPHORE_ID; | ||||
|  | ||||
|     /* Place the semaphore on the list of created semaphores.  First, | ||||
|        check for an empty list.  */ | ||||
|     if (_tx_semaphore_created_count == TX_EMPTY) | ||||
|     { | ||||
|  | ||||
|         /* The created semaphore list is empty.  Add semaphore to empty list.  */ | ||||
|         _tx_semaphore_created_ptr =                       semaphore_ptr; | ||||
|         semaphore_ptr -> tx_semaphore_created_next =      semaphore_ptr; | ||||
|         semaphore_ptr -> tx_semaphore_created_previous =  semaphore_ptr; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* This list is not NULL, add to the end of the list.  */ | ||||
|         next_semaphore =      _tx_semaphore_created_ptr; | ||||
|         previous_semaphore =  next_semaphore -> tx_semaphore_created_previous; | ||||
|  | ||||
|         /* Place the new semaphore in the list.  */ | ||||
|         next_semaphore -> tx_semaphore_created_previous =  semaphore_ptr; | ||||
|         previous_semaphore -> tx_semaphore_created_next =  semaphore_ptr; | ||||
|  | ||||
|         /* Setup this semaphore's next and previous created links.  */ | ||||
|         semaphore_ptr -> tx_semaphore_created_previous =  previous_semaphore; | ||||
|         semaphore_ptr -> tx_semaphore_created_next =      next_semaphore; | ||||
|     } | ||||
|  | ||||
|     /* Increment the created count.  */ | ||||
|     _tx_semaphore_created_count++; | ||||
|  | ||||
|     /* Optional semaphore create extended processing.  */ | ||||
|     TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr) | ||||
|  | ||||
|     /* If trace is enabled, register this object.  */ | ||||
|     TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_SEMAPHORE, semaphore_ptr, name_ptr, initial_count, 0) | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_CREATE, semaphore_ptr, initial_count, TX_POINTER_TO_ULONG_CONVERT(&next_semaphore), 0, TX_TRACE_SEMAPHORE_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_SEMAPHORE_CREATE_INSERT | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										209
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_delete.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_delete.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,209 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Semaphore                                                           */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_semaphore.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_semaphore_delete                                PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function deletes the specified semaphore.  All threads         */ | ||||
| /*    suspended on the semaphore are resumed with the TX_DELETED status   */ | ||||
| /*    code.                                                               */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    semaphore_ptr                     Pointer to semaphore control block*/ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_semaphore_delete(TX_SEMAPHORE *semaphore_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_THREAD       *next_thread; | ||||
| UINT            suspended_count; | ||||
| TX_SEMAPHORE    *next_semaphore; | ||||
| TX_SEMAPHORE    *previous_semaphore; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to remove the semaphore from the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_DELETE, semaphore_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_SEMAPHORE_EVENTS) | ||||
|  | ||||
|     /* Optional semaphore delete extended processing.  */ | ||||
|     TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr) | ||||
|  | ||||
|     /* If trace is enabled, unregister this object.  */ | ||||
|     TX_TRACE_OBJECT_UNREGISTER(semaphore_ptr) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_SEMAPHORE_DELETE_INSERT | ||||
|  | ||||
|     /* Clear the semaphore ID to make it invalid.  */ | ||||
|     semaphore_ptr -> tx_semaphore_id =  TX_CLEAR_ID; | ||||
|  | ||||
|     /* Decrement the number of semaphores.  */ | ||||
|     _tx_semaphore_created_count--; | ||||
|  | ||||
|     /* See if the semaphore is the only one on the list.  */ | ||||
|     if (_tx_semaphore_created_count == TX_EMPTY) | ||||
|     { | ||||
|  | ||||
|         /* Only created semaphore, just set the created list to NULL.  */ | ||||
|         _tx_semaphore_created_ptr =  TX_NULL; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Link-up the neighbors.  */ | ||||
|         next_semaphore =                                   semaphore_ptr -> tx_semaphore_created_next; | ||||
|         previous_semaphore =                               semaphore_ptr -> tx_semaphore_created_previous; | ||||
|         next_semaphore -> tx_semaphore_created_previous =  previous_semaphore; | ||||
|         previous_semaphore -> tx_semaphore_created_next =  next_semaphore; | ||||
|  | ||||
|         /* See if we have to update the created list head pointer.  */ | ||||
|         if (_tx_semaphore_created_ptr == semaphore_ptr) | ||||
|         { | ||||
|  | ||||
|             /* Yes, move the head pointer to the next link. */ | ||||
|             _tx_semaphore_created_ptr =  next_semaphore; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Temporarily disable preemption.  */ | ||||
|     _tx_thread_preempt_disable++; | ||||
|  | ||||
|     /* Pickup the suspension information.  */ | ||||
|     thread_ptr =                                     semaphore_ptr -> tx_semaphore_suspension_list; | ||||
|     semaphore_ptr -> tx_semaphore_suspension_list =  TX_NULL; | ||||
|     suspended_count =                                semaphore_ptr -> tx_semaphore_suspended_count; | ||||
|     semaphore_ptr -> tx_semaphore_suspended_count =  TX_NO_SUSPENSIONS; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Walk through the semaphore list to resume any and all threads suspended | ||||
|        on this semaphore.  */ | ||||
|     while (suspended_count != TX_NO_SUSPENSIONS) | ||||
|     { | ||||
|  | ||||
|         /* Decrement the suspension count.  */ | ||||
|         suspended_count--; | ||||
|  | ||||
|         /* Lockout interrupts.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* Clear the cleanup pointer, this prevents the timeout from doing | ||||
|            anything.  */ | ||||
|         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
|         /* Set the return status in the thread to TX_DELETED.  */ | ||||
|         thread_ptr -> tx_thread_suspend_status =  TX_DELETED; | ||||
|  | ||||
|         /* Move the thread pointer ahead.  */ | ||||
|         next_thread =  thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Resume the thread!  */ | ||||
|         _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #else | ||||
|  | ||||
|         /* Temporarily disable preemption again.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Resume the thread.  */ | ||||
|         _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|         /* Move to next thread.  */ | ||||
|         thread_ptr =  next_thread; | ||||
|     } | ||||
|  | ||||
|     /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h.  */ | ||||
|     TX_SEMAPHORE_DELETE_PORT_COMPLETION(semaphore_ptr) | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Release previous preempt disable.  */ | ||||
|     _tx_thread_preempt_disable--; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Check for preemption.  */ | ||||
|     _tx_thread_system_preempt_check(); | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										234
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_get.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_get.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,234 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Semaphore                                                           */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_semaphore.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_semaphore_get                                   PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function gets an instance from the specified counting          */ | ||||
| /*    semaphore.                                                          */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    semaphore_ptr                     Pointer to semaphore control block*/ | ||||
| /*    wait_option                       Suspension option                 */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_suspend         Suspend thread service            */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| UINT            status; | ||||
|  | ||||
|  | ||||
|     /* Default the status to TX_SUCCESS.  */ | ||||
|     status =  TX_SUCCESS; | ||||
|  | ||||
|     /* Disable interrupts to get an instance from the semaphore.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Increment the total semaphore get counter.  */ | ||||
|     _tx_semaphore_performance_get_count++; | ||||
|  | ||||
|     /* Increment the number of attempts to get this semaphore.  */ | ||||
|     semaphore_ptr -> tx_semaphore_performance_get_count++; | ||||
| #endif | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_GET, semaphore_ptr, wait_option, semaphore_ptr -> tx_semaphore_count, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), TX_TRACE_SEMAPHORE_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_SEMAPHORE_GET_INSERT | ||||
|  | ||||
|     /* Determine if there is an instance of the semaphore.  */ | ||||
|     if (semaphore_ptr -> tx_semaphore_count != ((ULONG) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Decrement the semaphore count.  */ | ||||
|         semaphore_ptr -> tx_semaphore_count--; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|  | ||||
|     /* Determine if the request specifies suspension.  */ | ||||
|     else if (wait_option != TX_NO_WAIT) | ||||
|     { | ||||
|  | ||||
|         /* Determine if the preempt disable flag is non-zero.  */ | ||||
|         if (_tx_thread_preempt_disable != ((UINT) 0)) | ||||
|         { | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion.  */ | ||||
|             status =  TX_NO_INSTANCE; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Prepare for suspension of this thread.  */ | ||||
|  | ||||
| #ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|             /* Increment the total semaphore suspensions counter.  */ | ||||
|             _tx_semaphore_performance_suspension_count++; | ||||
|  | ||||
|             /* Increment the number of suspensions on this semaphore.  */ | ||||
|             semaphore_ptr -> tx_semaphore_performance_suspension_count++; | ||||
| #endif | ||||
|  | ||||
|             /* Pickup thread pointer.  */ | ||||
|             TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
|             /* Setup cleanup routine pointer.  */ | ||||
|             thread_ptr -> tx_thread_suspend_cleanup =  &(_tx_semaphore_cleanup); | ||||
|  | ||||
|             /* Setup cleanup information, i.e. this semaphore control | ||||
|                block.  */ | ||||
|             thread_ptr -> tx_thread_suspend_control_block =  (VOID *) semaphore_ptr; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Increment the suspension sequence number, which is used to identify | ||||
|                this suspension event.  */ | ||||
|             thread_ptr -> tx_thread_suspension_sequence++; | ||||
| #endif | ||||
|  | ||||
|             /* Setup suspension list.  */ | ||||
|             if (semaphore_ptr -> tx_semaphore_suspended_count == TX_NO_SUSPENSIONS) | ||||
|             { | ||||
|  | ||||
|                 /* No other threads are suspended.  Setup the head pointer and | ||||
|                    just setup this threads pointers to itself.  */ | ||||
|                 semaphore_ptr -> tx_semaphore_suspension_list =         thread_ptr; | ||||
|                 thread_ptr -> tx_thread_suspended_next =                thread_ptr; | ||||
|                 thread_ptr -> tx_thread_suspended_previous =            thread_ptr; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* This list is not NULL, add current thread to the end. */ | ||||
|                 next_thread =                                   semaphore_ptr -> tx_semaphore_suspension_list; | ||||
|                 thread_ptr -> tx_thread_suspended_next =        next_thread; | ||||
|                 previous_thread =                               next_thread -> tx_thread_suspended_previous; | ||||
|                 thread_ptr -> tx_thread_suspended_previous =    previous_thread; | ||||
|                 previous_thread -> tx_thread_suspended_next =   thread_ptr; | ||||
|                 next_thread -> tx_thread_suspended_previous =   thread_ptr; | ||||
|             } | ||||
|  | ||||
|             /* Increment the number of suspensions.  */ | ||||
|             semaphore_ptr -> tx_semaphore_suspended_count++; | ||||
|  | ||||
|             /* Set the state to suspended.  */ | ||||
|             thread_ptr -> tx_thread_state =    TX_SEMAPHORE_SUSP; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Call actual non-interruptable thread suspension routine.  */ | ||||
|             _tx_thread_system_ni_suspend(thread_ptr, wait_option); | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #else | ||||
|  | ||||
|             /* Set the suspending flag.  */ | ||||
|             thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|             /* Setup the timeout period.  */ | ||||
|             thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  wait_option; | ||||
|  | ||||
|             /* Temporarily disable preemption.  */ | ||||
|             _tx_thread_preempt_disable++; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Call actual thread suspension routine.  */ | ||||
|             _tx_thread_system_suspend(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|             /* Return the completion status.  */ | ||||
|             status =  thread_ptr -> tx_thread_suspend_status; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Immediate return, return error completion.  */ | ||||
|         status =  TX_NO_INSTANCE; | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										141
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_info_get.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_info_get.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Semaphore                                                           */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_semaphore.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_semaphore_info_get                              PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function retrieves information from the specified semaphore.   */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    semaphore_ptr                     Pointer to semaphore control block*/ | ||||
| /*    name                              Destination for the semaphore name*/ | ||||
| /*    current_value                     Destination for current value of  */ | ||||
| /*                                        the semaphore                   */ | ||||
| /*    first_suspended                   Destination for pointer of first  */ | ||||
| /*                                        thread suspended on semaphore   */ | ||||
| /*    suspended_count                   Destination for suspended count   */ | ||||
| /*    next_semaphore                    Destination for pointer to next   */ | ||||
| /*                                        semaphore on the created list   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value, | ||||
|                     TX_THREAD **first_suspended, ULONG *suspended_count, | ||||
|                     TX_SEMAPHORE **next_semaphore) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_INFO_GET, semaphore_ptr, 0, 0, 0, TX_TRACE_SEMAPHORE_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_SEMAPHORE_INFO_GET_INSERT | ||||
|  | ||||
|     /* Retrieve all the pertinent information and return it in the supplied | ||||
|        destinations.  */ | ||||
|  | ||||
|     /* Retrieve the name of the semaphore.  */ | ||||
|     if (name != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *name =  semaphore_ptr -> tx_semaphore_name; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the current value of the semaphore.  */ | ||||
|     if (current_value != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *current_value =  semaphore_ptr -> tx_semaphore_count; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the first thread suspended on this semaphore.  */ | ||||
|     if (first_suspended != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *first_suspended =  semaphore_ptr -> tx_semaphore_suspension_list; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the number of threads suspended on this semaphore.  */ | ||||
|     if (suspended_count != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *suspended_count =  (ULONG) semaphore_ptr -> tx_semaphore_suspended_count; | ||||
|     } | ||||
|  | ||||
|     /* Retrieve the pointer to the next semaphore created.  */ | ||||
|     if (next_semaphore != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *next_semaphore =  semaphore_ptr -> tx_semaphore_created_next; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										133
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_initialize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_initialize.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Semaphore                                                           */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_semaphore.h" | ||||
|  | ||||
|  | ||||
| #ifndef TX_INLINE_INITIALIZATION | ||||
|  | ||||
| /* Locate semaphore component data in this file.  */ | ||||
|  | ||||
| /* Define the head pointer of the created semaphore list.  */ | ||||
|  | ||||
| TX_SEMAPHORE *   _tx_semaphore_created_ptr; | ||||
|  | ||||
|  | ||||
| /* Define the variable that holds the number of created semaphores. */ | ||||
|  | ||||
| ULONG            _tx_semaphore_created_count; | ||||
|  | ||||
|  | ||||
| #ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
| /* Define the total number of semaphore puts.  */ | ||||
|  | ||||
| ULONG            _tx_semaphore_performance_put_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of semaphore gets.  */ | ||||
|  | ||||
| ULONG            _tx_semaphore_performance_get_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of semaphore suspensions.  */ | ||||
|  | ||||
| ULONG            _tx_semaphore_performance_suspension_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of semaphore timeouts.  */ | ||||
|  | ||||
| ULONG            _tx_semaphore_performance_timeout_count; | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_semaphore_initialize                            PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function initializes the various control data structures for   */ | ||||
| /*    the semaphore component.                                            */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_initialize_high_level         High level initialization         */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            opt out of function when    */ | ||||
| /*                                            TX_INLINE_INITIALIZATION is */ | ||||
| /*                                            defined,                    */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_semaphore_initialize(VOID) | ||||
| { | ||||
|  | ||||
| #ifndef TX_DISABLE_REDUNDANT_CLEARING | ||||
|  | ||||
|     /* Initialize the head pointer of the created semaphores list and the | ||||
|        number of semaphores created.  */ | ||||
|     _tx_semaphore_created_ptr =        TX_NULL; | ||||
|     _tx_semaphore_created_count =      TX_EMPTY; | ||||
|  | ||||
| #ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Initialize semaphore performance counters.  */ | ||||
|     _tx_semaphore_performance_put_count =         ((ULONG) 0); | ||||
|     _tx_semaphore_performance_get_count =         ((ULONG) 0); | ||||
|     _tx_semaphore_performance_suspension_count =  ((ULONG) 0); | ||||
|     _tx_semaphore_performance_timeout_count =     ((ULONG) 0); | ||||
| #endif | ||||
| #endif | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										253
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_prioritize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_prioritize.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,253 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Semaphore                                                           */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_semaphore.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_semaphore_prioritize                            PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function places the highest priority suspended thread at the   */ | ||||
| /*    front of the suspension list.  All other threads remain in the same */ | ||||
| /*    FIFO suspension order.                                              */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    semaphore_ptr                     Pointer to semaphore control block*/ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_semaphore_prioritize(TX_SEMAPHORE *semaphore_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| TX_THREAD       *priority_thread_ptr; | ||||
| TX_THREAD       *head_ptr; | ||||
| UINT            suspended_count; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| UINT            list_changed; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PRIORITIZE, semaphore_ptr, semaphore_ptr -> tx_semaphore_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_SEMAPHORE_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_SEMAPHORE_PRIORITIZE_INSERT | ||||
|  | ||||
|     /* Pickup the suspended count.  */ | ||||
|     suspended_count =  semaphore_ptr -> tx_semaphore_suspended_count; | ||||
|  | ||||
|     /* Determine if there are fewer than 2 suspended threads.  */ | ||||
|     if (suspended_count < ((UINT) 2)) | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|  | ||||
|     /* Determine if there how many threads are suspended on this semaphore.  */ | ||||
|     else if (suspended_count == ((UINT) 2)) | ||||
|     { | ||||
|  | ||||
|         /* Pickup the head pointer and the next pointer.  */ | ||||
|         head_ptr =  semaphore_ptr -> tx_semaphore_suspension_list; | ||||
|         next_thread =  head_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|         /* Determine if the next suspended thread has a higher priority.  */ | ||||
|         if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority)) | ||||
|         { | ||||
|  | ||||
|             /* Yes, move the list head to the next thread.  */ | ||||
|             semaphore_ptr -> tx_semaphore_suspension_list =  next_thread; | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Remember the suspension count and head pointer.  */ | ||||
|         head_ptr =   semaphore_ptr -> tx_semaphore_suspension_list; | ||||
|  | ||||
|         /* Default the highest priority thread to the thread at the front of the list.  */ | ||||
|         priority_thread_ptr =  head_ptr; | ||||
|  | ||||
|         /* Setup search pointer.  */ | ||||
|         thread_ptr =  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|         /* Disable preemption.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Set the list changed flag to false.  */ | ||||
|         list_changed =  TX_FALSE; | ||||
|  | ||||
|         /* Search through the list to find the highest priority thread.  */ | ||||
|         do | ||||
|         { | ||||
|  | ||||
|             /* Is the current thread higher priority?  */ | ||||
|             if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, remember that this thread is the highest priority.  */ | ||||
|                 priority_thread_ptr =  thread_ptr; | ||||
|             } | ||||
|  | ||||
|             /* Restore interrupts temporarily.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Disable interrupts again.  */ | ||||
|             TX_DISABLE | ||||
|  | ||||
|             /* Determine if any changes to the list have occurred while | ||||
|                interrupts were enabled.  */ | ||||
|  | ||||
|             /* Is the list head the same?  */ | ||||
|             if (head_ptr != semaphore_ptr -> tx_semaphore_suspension_list) | ||||
|             { | ||||
|  | ||||
|                 /* The list head has changed, set the list changed flag.  */ | ||||
|                 list_changed =  TX_TRUE; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Is the suspended count the same?  */ | ||||
|                 if (suspended_count != semaphore_ptr -> tx_semaphore_suspended_count) | ||||
|                 { | ||||
|  | ||||
|                     /* The list head has changed, set the list changed flag.  */ | ||||
|                     list_changed =  TX_TRUE; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             /* Determine if the list has changed.  */ | ||||
|             if (list_changed == TX_FALSE) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, everything is the same... move the thread pointer to the next thread.  */ | ||||
|                 thread_ptr =  thread_ptr -> tx_thread_suspended_next; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* No, the list is been modified so we need to start the search over.  */ | ||||
|  | ||||
|                 /* Save the suspension count and head pointer.  */ | ||||
|                 head_ptr =   semaphore_ptr -> tx_semaphore_suspension_list; | ||||
|                 suspended_count =  semaphore_ptr -> tx_semaphore_suspended_count; | ||||
|  | ||||
|                 /* Default the highest priority thread to the thread at the front of the list.  */ | ||||
|                 priority_thread_ptr =  head_ptr; | ||||
|  | ||||
|                 /* Setup search pointer.  */ | ||||
|                 thread_ptr =  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|  | ||||
|                 /* Reset the list changed flag.  */ | ||||
|                 list_changed =  TX_FALSE; | ||||
|             } | ||||
|  | ||||
|         } while (thread_ptr != head_ptr); | ||||
|  | ||||
|         /* Release preemption.  */ | ||||
|         _tx_thread_preempt_disable--; | ||||
|  | ||||
|         /* Now determine if the highest priority thread is at the front | ||||
|            of the list.  */ | ||||
|         if (priority_thread_ptr != head_ptr) | ||||
|         { | ||||
|  | ||||
|             /* No, we need to move the highest priority suspended thread to the | ||||
|                front of the list.  */ | ||||
|  | ||||
|             /* First, remove the highest priority thread by updating the | ||||
|                adjacent suspended threads.  */ | ||||
|             next_thread =                                  priority_thread_ptr -> tx_thread_suspended_next; | ||||
|             previous_thread =                              priority_thread_ptr -> tx_thread_suspended_previous; | ||||
|             next_thread -> tx_thread_suspended_previous =  previous_thread; | ||||
|             previous_thread -> tx_thread_suspended_next =  next_thread; | ||||
|  | ||||
|             /* Now, link the highest priority thread at the front of the list.  */ | ||||
|             previous_thread =                                      head_ptr -> tx_thread_suspended_previous; | ||||
|             priority_thread_ptr -> tx_thread_suspended_next =      head_ptr; | ||||
|             priority_thread_ptr -> tx_thread_suspended_previous =  previous_thread; | ||||
|             previous_thread -> tx_thread_suspended_next =          priority_thread_ptr; | ||||
|             head_ptr -> tx_thread_suspended_previous =             priority_thread_ptr; | ||||
|  | ||||
|             /* Move the list head pointer to the highest priority suspended thread.  */ | ||||
|             semaphore_ptr -> tx_semaphore_suspension_list =  priority_thread_ptr; | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Check for preemption.  */ | ||||
|         _tx_thread_system_preempt_check(); | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										224
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_put.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_put.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,224 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Semaphore                                                           */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_semaphore.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_semaphore_put                                   PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function puts an instance into the specified counting          */ | ||||
| /*    semaphore.                                                          */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    semaphore_ptr                     Pointer to semaphore control block*/ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Success completion status         */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread service             */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_semaphore_put(TX_SEMAPHORE *semaphore_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
| VOID            (*semaphore_put_notify)(struct TX_SEMAPHORE_STRUCT *notify_semaphore_ptr); | ||||
| #endif | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| UINT            suspended_count; | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to put an instance back to the semaphore.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Increment the total semaphore put counter.  */ | ||||
|     _tx_semaphore_performance_put_count++; | ||||
|  | ||||
|     /* Increment the number of puts on this semaphore.  */ | ||||
|     semaphore_ptr -> tx_semaphore_performance_put_count++; | ||||
| #endif | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PUT, semaphore_ptr, semaphore_ptr -> tx_semaphore_count, semaphore_ptr -> tx_semaphore_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), TX_TRACE_SEMAPHORE_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_SEMAPHORE_PUT_INSERT | ||||
|  | ||||
|     /* Pickup the number of suspended threads.  */ | ||||
|     suspended_count =  semaphore_ptr -> tx_semaphore_suspended_count; | ||||
|  | ||||
|     /* Determine if there are any threads suspended on the semaphore.  */ | ||||
|     if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|     { | ||||
|  | ||||
|         /* Increment the semaphore count.  */ | ||||
|         semaphore_ptr -> tx_semaphore_count++; | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|         /* Pickup the application notify function.  */ | ||||
|         semaphore_put_notify =  semaphore_ptr -> tx_semaphore_put_notify; | ||||
| #endif | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|         /* Determine if notification is required.  */ | ||||
|         if (semaphore_put_notify != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Yes, call the appropriate notify callback function.  */ | ||||
|             (semaphore_put_notify)(semaphore_ptr); | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* A thread is suspended on this semaphore.  */ | ||||
|  | ||||
|         /* Pickup the pointer to the first suspended thread.  */ | ||||
|         thread_ptr =  semaphore_ptr -> tx_semaphore_suspension_list; | ||||
|  | ||||
|         /* Remove the suspended thread from the list.  */ | ||||
|  | ||||
|         /* See if this is the only suspended thread on the list.  */ | ||||
|         suspended_count--; | ||||
|         if (suspended_count == TX_NO_SUSPENSIONS) | ||||
|         { | ||||
|  | ||||
|             /* Yes, the only suspended thread.  */ | ||||
|  | ||||
|             /* Update the head pointer.  */ | ||||
|             semaphore_ptr -> tx_semaphore_suspension_list =  TX_NULL; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* At least one more thread is on the same expiration list.  */ | ||||
|  | ||||
|             /* Update the list head pointer.  */ | ||||
|             next_thread =                                     thread_ptr -> tx_thread_suspended_next; | ||||
|             semaphore_ptr -> tx_semaphore_suspension_list =   next_thread; | ||||
|  | ||||
|             /* Update the links of the adjacent threads.  */ | ||||
|             previous_thread =                               thread_ptr -> tx_thread_suspended_previous; | ||||
|             next_thread -> tx_thread_suspended_previous =   previous_thread; | ||||
|             previous_thread -> tx_thread_suspended_next =   next_thread; | ||||
|         } | ||||
|  | ||||
|         /* Decrement the suspension count.  */ | ||||
|         semaphore_ptr -> tx_semaphore_suspended_count =  suspended_count; | ||||
|  | ||||
|         /* Prepare for resumption of the first thread.  */ | ||||
|  | ||||
|         /* Clear cleanup routine to avoid timeout.  */ | ||||
|         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|         /* Pickup the application notify function.  */ | ||||
|         semaphore_put_notify =  semaphore_ptr -> tx_semaphore_put_notify; | ||||
| #endif | ||||
|  | ||||
|         /* Put return status into the thread control block.  */ | ||||
|         thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Resume the thread!  */ | ||||
|         _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #else | ||||
|  | ||||
|         /* Temporarily disable preemption.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Resume thread.  */ | ||||
|         _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|         /* Determine if notification is required.  */ | ||||
|         if (semaphore_put_notify != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Yes, call the appropriate notify callback function.  */ | ||||
|             (semaphore_put_notify)(semaphore_ptr); | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     /* Return successful completion.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										109
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_put_notify.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								Middlewares/ST/threadx/common/src/tx_semaphore_put_notify.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Semaphore                                                           */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_semaphore.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_semaphore_put_notify                            PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function registers an application callback function that is    */ | ||||
| /*    called whenever the this semaphore is put.                          */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    semaphore_ptr                         Pointer to semaphore          */ | ||||
| /*    semaphore_put_notify                  Application callback function */ | ||||
| /*                                            (TX_NULL disables notify)   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Service return status         */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_semaphore_put_notify(TX_SEMAPHORE *semaphore_ptr, VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)) | ||||
| { | ||||
|  | ||||
| #ifdef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|     TX_SEMAPHORE_NOT_USED(semaphore_ptr); | ||||
|     TX_SEMAPHORE_PUT_NOTIFY_NOT_USED(semaphore_put_notify); | ||||
|  | ||||
|     /* Feature is not enabled, return error.  */ | ||||
|     return(TX_FEATURE_NOT_ENABLED); | ||||
| #else | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Make entry in event log.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PUT_NOTIFY, semaphore_ptr, 0, 0, 0, TX_TRACE_SEMAPHORE_EVENTS) | ||||
|  | ||||
|     /* Make entry in event log.  */ | ||||
|     TX_EL_SEMAPHORE_PUT_NOTIFY_INSERT | ||||
|  | ||||
|     /* Setup semaphore put notification callback function.  */ | ||||
|     semaphore_ptr -> tx_semaphore_put_notify =  semaphore_put_notify; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return success to caller.  */ | ||||
|     return(TX_SUCCESS); | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										391
									
								
								Middlewares/ST/threadx/common/src/tx_thread_create.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										391
									
								
								Middlewares/ST/threadx/common/src/tx_thread_create.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,391 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_initialize.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_create                                   PORTABLE C      */ | ||||
| /*                                                           6.3.0        */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function creates a thread and places it on the list of created */ | ||||
| /*    threads.                                                            */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                            Thread control block pointer  */ | ||||
| /*    name                                  Pointer to thread name string */ | ||||
| /*    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                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    return status                         Thread create return status   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_stack_build                Build initial thread stack    */ | ||||
| /*    _tx_thread_system_resume              Resume automatic start thread */ | ||||
| /*    _tx_thread_system_ni_resume           Noninterruptable resume thread*/ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*    _tx_timer_initialize                  Create system timer thread    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020      William E. Lamie        Initial Version 6.0           */ | ||||
| /*  09-30-2020      William E. Lamie        Modified comment(s), and      */ | ||||
| /*                                            changed stack calculations  */ | ||||
| /*                                            to use ALIGN_TYPE integers, */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*  06-02-2021      William E. Lamie        Modified comment(s), and      */ | ||||
| /*                                            supported TX_MISRA_ENABLE,  */ | ||||
| /*  08-02-2021      Scott Larson            Removed unneeded cast,        */ | ||||
| /*                                            resulting in version 6.1.8  */ | ||||
| /*  10-31-2023      Xiuwen Cai              Modified comment(s),          */ | ||||
| /*                                            added option for random     */ | ||||
| /*                                            number stack filling,       */ | ||||
| /*                                            resulting in version 6.3.0  */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, 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) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD               *next_thread; | ||||
| TX_THREAD               *previous_thread; | ||||
| TX_THREAD               *saved_thread_ptr; | ||||
| UINT                    saved_threshold =  ((UINT) 0); | ||||
| UCHAR                   *temp_ptr; | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
| ALIGN_TYPE              new_stack_start; | ||||
| ALIGN_TYPE              updated_stack_start; | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_DISABLE_STACK_FILLING | ||||
| #if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING) | ||||
|  | ||||
|     /* Initialize the stack fill value to a 8-bit random value.  */ | ||||
|     thread_ptr -> tx_thread_stack_fill_value = ((ULONG) TX_RAND()) & 0xFFUL; | ||||
|  | ||||
|     /* Duplicate the random value in each of the 4 bytes of the stack fill value.  */ | ||||
|     thread_ptr -> tx_thread_stack_fill_value = thread_ptr -> tx_thread_stack_fill_value | | ||||
|                     (thread_ptr -> tx_thread_stack_fill_value << 8) | | ||||
|                     (thread_ptr -> tx_thread_stack_fill_value << 16) | | ||||
|                     (thread_ptr -> tx_thread_stack_fill_value << 24); | ||||
| #endif | ||||
|  | ||||
|     /* 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(stack_start, ((UCHAR) TX_STACK_FILL), stack_size); | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|  | ||||
|     /* 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)); | ||||
|  | ||||
|     /* Ensure the starting stack address is evenly aligned.  */ | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|     new_stack_start = TX_POINTER_TO_ULONG_CONVERT(stack_start); | ||||
| #else | ||||
|     new_stack_start =  TX_POINTER_TO_ALIGN_TYPE_CONVERT(stack_start); | ||||
| #endif /* TX_MISRA_ENABLE */ | ||||
|     updated_stack_start =  (((new_stack_start) + ((sizeof(ULONG)) - ((ULONG) 1)) ) & (~((sizeof(ULONG)) - ((ULONG) 1)))); | ||||
|  | ||||
|     /* Determine if the starting stack address is different.  */ | ||||
|     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)); | ||||
|     } | ||||
|  | ||||
|     /* Update the starting stack pointer.  */ | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|     stack_start = TX_ULONG_TO_POINTER_CONVERT(updated_stack_start); | ||||
| #else | ||||
|     stack_start =  TX_ALIGN_TYPE_TO_POINTER_CONVERT(updated_stack_start); | ||||
| #endif /* TX_MISRA_ENABLE */ | ||||
| #endif | ||||
|  | ||||
|     /* Prepare the thread control block prior to placing it on the created | ||||
|        list.  */ | ||||
|  | ||||
|     /* Initialize thread control block to all zeros.  */ | ||||
|     TX_MEMSET(thread_ptr, 0, (sizeof(TX_THREAD))); | ||||
|  | ||||
|     /* Place the supplied parameters into the thread's control block.  */ | ||||
|     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); | ||||
|  | ||||
|     /* 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); | ||||
|  | ||||
| #ifndef TX_DISABLE_PREEMPTION_THRESHOLD | ||||
|  | ||||
|     /* Preemption-threshold is enabled, setup accordingly.  */ | ||||
|     thread_ptr -> tx_thread_preempt_threshold =       preempt_threshold; | ||||
|     thread_ptr -> tx_thread_user_preempt_threshold =  preempt_threshold; | ||||
| #else | ||||
|  | ||||
|     /* Preemption-threshold is disabled, determine if preemption-threshold was required.  */ | ||||
|     if (priority != preempt_threshold) | ||||
|     { | ||||
|  | ||||
|         /* Preemption-threshold specified. Since specific preemption-threshold is not supported, | ||||
|            disable all preemption.  */ | ||||
|         thread_ptr -> tx_thread_preempt_threshold =       ((UINT) 0); | ||||
|         thread_ptr -> tx_thread_user_preempt_threshold =  ((UINT) 0); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Preemption-threshold is not specified, just setup with the priority.  */ | ||||
|         thread_ptr -> tx_thread_preempt_threshold =       priority; | ||||
|         thread_ptr -> tx_thread_user_preempt_threshold =  priority; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     /* Now fill in the values that are required for thread initialization.  */ | ||||
|     thread_ptr -> tx_thread_state =  TX_SUSPENDED; | ||||
|  | ||||
|     /* 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) | ||||
|  | ||||
|     /* Call the target specific stack frame building routine to build the | ||||
|        thread's initial stack and to setup the actual stack pointer in the | ||||
|        control block.  */ | ||||
|     _tx_thread_stack_build(thread_ptr, _tx_thread_shell_entry); | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|  | ||||
|     /* Setup the highest usage stack pointer.  */ | ||||
|     thread_ptr -> tx_thread_stack_highest_ptr =  thread_ptr -> tx_thread_stack_ptr; | ||||
| #endif | ||||
|  | ||||
|     /* Prepare to make this thread a member of the created thread list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Load the thread ID field in the thread control block.  */ | ||||
|     thread_ptr -> tx_thread_id =  TX_THREAD_ID; | ||||
|  | ||||
|     /* Place the thread on the list of created threads.  First, | ||||
|        check for an empty list.  */ | ||||
|     if (_tx_thread_created_count == TX_EMPTY) | ||||
|     { | ||||
|  | ||||
|         /* The created thread list is empty.  Add thread to empty list.  */ | ||||
|         _tx_thread_created_ptr =                    thread_ptr; | ||||
|         thread_ptr -> tx_thread_created_next =      thread_ptr; | ||||
|         thread_ptr -> tx_thread_created_previous =  thread_ptr; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* This list is not NULL, add to the end of the list.  */ | ||||
|         next_thread =  _tx_thread_created_ptr; | ||||
|         previous_thread =  next_thread -> tx_thread_created_previous; | ||||
|  | ||||
|         /* Place the new thread in the list.  */ | ||||
|         next_thread -> tx_thread_created_previous =  thread_ptr; | ||||
|         previous_thread -> tx_thread_created_next =  thread_ptr; | ||||
|  | ||||
|         /* Setup this thread's created links.  */ | ||||
|         thread_ptr -> tx_thread_created_previous =  previous_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_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, 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) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_THREAD_CREATE_INSERT | ||||
|  | ||||
| #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) | ||||
|         { | ||||
|  | ||||
|             /* Yes, this create call was made from initialization.  */ | ||||
|  | ||||
|             /* Pickup the current thread execute pointer, which corresponds to the | ||||
|                highest priority thread ready to execute.  Interrupt lockout is | ||||
|                not required, since interrupts are assumed to be disabled during | ||||
|                initialization.  */ | ||||
|             saved_thread_ptr =  _tx_thread_execute_ptr; | ||||
|  | ||||
|             /* Determine if there is thread ready for execution.  */ | ||||
|             if (saved_thread_ptr != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, a thread is ready for execution when initialization completes.  */ | ||||
|  | ||||
|                 /* Save the current preemption-threshold.  */ | ||||
|                 saved_threshold =  saved_thread_ptr -> tx_thread_preempt_threshold; | ||||
|  | ||||
|                 /* For initialization, temporarily set the preemption-threshold to the | ||||
|                    priority level to make sure the highest-priority thread runs once | ||||
|                    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; | ||||
|         } | ||||
|  | ||||
| #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); | ||||
|  | ||||
|         /* Restore previous interrupt posture.  */ | ||||
|         TX_RESTORE | ||||
| #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); | ||||
| #endif | ||||
|  | ||||
|         /* Determine if the thread's preemption-threshold needs to be restored.  */ | ||||
|         if (saved_thread_ptr != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* 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; | ||||
|         } | ||||
|     } | ||||
|     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 | ||||
|     } | ||||
|  | ||||
|     /* Always return a success.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										168
									
								
								Middlewares/ST/threadx/common/src/tx_thread_delete.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								Middlewares/ST/threadx/common/src/tx_thread_delete.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,168 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_delete                                   PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function handles application delete thread requests.  The      */ | ||||
| /*    thread to delete must be in a terminated or completed state,        */ | ||||
| /*    otherwise this function just returns an error code.                 */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                            Pointer to thread to suspend  */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Return completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_thread_delete(TX_THREAD *thread_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *next_thread; | ||||
| TX_THREAD       *previous_thread; | ||||
| UINT            status; | ||||
|  | ||||
|  | ||||
|     /* Default status to success.  */ | ||||
|     status =  TX_SUCCESS; | ||||
|  | ||||
|     /* Lockout interrupts while the thread is being deleted.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Check for proper status of this thread to delete.  */ | ||||
|     if (thread_ptr -> tx_thread_state != TX_COMPLETED) | ||||
|     { | ||||
|  | ||||
|         /* Now check for terminated state.  */ | ||||
|         if (thread_ptr -> tx_thread_state != TX_TERMINATED) | ||||
|         { | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Thread not completed or terminated - return an error!  */ | ||||
|             status =  TX_DELETE_ERROR; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Determine if the delete operation is okay.  */ | ||||
|     if (status == TX_SUCCESS) | ||||
|     { | ||||
|  | ||||
|         /* Yes, continue with deleting the thread.  */ | ||||
|  | ||||
|         /* Perform any additional activities for tool or user purpose.  */ | ||||
|         TX_THREAD_DELETE_EXTENSION(thread_ptr) | ||||
|  | ||||
|         /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|         TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_DELETE, thread_ptr, TX_POINTER_TO_ULONG_CONVERT(&next_thread), 0, 0, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|         /* If trace is enabled, unregister this object.  */ | ||||
|         TX_TRACE_OBJECT_UNREGISTER(thread_ptr) | ||||
|  | ||||
|         /* Log this kernel call.  */ | ||||
|         TX_EL_THREAD_DELETE_INSERT | ||||
|  | ||||
|         /* Unregister thread in the thread array structure.  */ | ||||
|         TX_EL_THREAD_UNREGISTER(thread_ptr) | ||||
|  | ||||
|         /* Clear the thread ID to make it invalid.  */ | ||||
|         thread_ptr -> tx_thread_id =  TX_CLEAR_ID; | ||||
|  | ||||
|         /* Decrement the number of created threads.  */ | ||||
|         _tx_thread_created_count--; | ||||
|  | ||||
|         /* See if the thread is the only one on the list.  */ | ||||
|         if (_tx_thread_created_count == TX_EMPTY) | ||||
|         { | ||||
|  | ||||
|             /* Only created thread, just set the created list to NULL.  */ | ||||
|             _tx_thread_created_ptr =  TX_NULL; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Otherwise, not the only created thread, link-up the neighbors.  */ | ||||
|             next_thread =                                thread_ptr -> tx_thread_created_next; | ||||
|             previous_thread =                            thread_ptr -> tx_thread_created_previous; | ||||
|             next_thread -> tx_thread_created_previous =  previous_thread; | ||||
|             previous_thread -> tx_thread_created_next =  next_thread; | ||||
|  | ||||
|             /* See if we have to update the created list head pointer.  */ | ||||
|             if (_tx_thread_created_ptr == thread_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, move the head pointer to the next link. */ | ||||
|                 _tx_thread_created_ptr =  next_thread; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h.  */ | ||||
|         TX_THREAD_DELETE_PORT_COMPLETION(thread_ptr) | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										111
									
								
								Middlewares/ST/threadx/common/src/tx_thread_entry_exit_notify.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								Middlewares/ST/threadx/common/src/tx_thread_entry_exit_notify.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_entry_exit_notify                        PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function registers an application entry/exit notification      */ | ||||
| /*    callback routine for the application. Once registered, the callback */ | ||||
| /*    routine is called when the thread is initially entered and called   */ | ||||
| /*    again when the thread completes or is terminated.                   */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                            Pointer to thread             */ | ||||
| /*    thread_entry_exit_notify              Pointer to notify callback    */ | ||||
| /*                                            function, TX_NULL to disable*/ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Service return status         */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_thread_entry_exit_notify(TX_THREAD *thread_ptr, VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)) | ||||
| { | ||||
|  | ||||
| #ifdef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|     TX_THREAD_NOT_USED(thread_ptr); | ||||
|     TX_THREAD_ENTRY_EXIT_NOTIFY_NOT_USED(thread_entry_exit_notify); | ||||
|  | ||||
|     /* Feature is not enabled, return error.  */ | ||||
|     return(TX_FEATURE_NOT_ENABLED); | ||||
| #else | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Make entry in event log.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_ENTRY_EXIT_NOTIFY, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|     /* Make entry in event log.  */ | ||||
|     TX_EL_THREAD_ENTRY_EXIT_NOTIFY_INSERT | ||||
|  | ||||
|     /* Setup thread entry/exit notification callback function.  */ | ||||
|     thread_ptr -> tx_thread_entry_exit_notify =  thread_entry_exit_notify; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return success to caller.  */ | ||||
|     return(TX_SUCCESS); | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										105
									
								
								Middlewares/ST/threadx/common/src/tx_thread_identify.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								Middlewares/ST/threadx/common/src/tx_thread_identify.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
| #include "tx_trace.h" | ||||
| #endif | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_identify                                 PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function returns the control block pointer of the currently    */ | ||||
| /*    executing thread.  If the return value is NULL, no thread is        */ | ||||
| /*    executing.                                                          */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_THREAD *                           Pointer to control block of   */ | ||||
| /*                                            currently executing thread  */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| TX_THREAD  *_tx_thread_identify(VOID) | ||||
| { | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to put the timer on the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_IDENTIFY, 0, 0, 0, 0, TX_TRACE_THREAD_EVENTS) | ||||
| #endif | ||||
|  | ||||
|    /* Log this kernel call.  */ | ||||
|     TX_EL_THREAD_IDENTIFY_INSERT | ||||
|  | ||||
|     /* Pickup thread pointer.  */ | ||||
|     TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return the current thread pointer.  */ | ||||
|     return(thread_ptr); | ||||
| } | ||||
|  | ||||
							
								
								
									
										165
									
								
								Middlewares/ST/threadx/common/src/tx_thread_info_get.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								Middlewares/ST/threadx/common/src/tx_thread_info_get.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_info_get                                 PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function retrieves information from the specified thread.      */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                        Pointer to thread control block   */ | ||||
| /*    name                              Destination for the thread name   */ | ||||
| /*    state                             Destination for thread state      */ | ||||
| /*    run_count                         Destination for thread run count  */ | ||||
| /*    priority                          Destination for thread priority   */ | ||||
| /*    preemption_threshold              Destination for thread preemption-*/ | ||||
| /*                                        threshold                       */ | ||||
| /*    time_slice                        Destination for thread time-slice */ | ||||
| /*    next_thread                       Destination for next created      */ | ||||
| /*                                        thread                          */ | ||||
| /*    next_suspended_thread             Destination for next suspended    */ | ||||
| /*                                        thread                          */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count, | ||||
|                 UINT *priority, UINT *preemption_threshold, ULONG *time_slice, | ||||
|                 TX_THREAD **next_thread, TX_THREAD **next_suspended_thread) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_INFO_GET, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_THREAD_INFO_GET_INSERT | ||||
|  | ||||
|     /* Retrieve all the pertinent information and return it in the supplied | ||||
|        destinations.  */ | ||||
|  | ||||
|     /* Retrieve the name of the thread.  */ | ||||
|     if (name != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *name =  thread_ptr -> tx_thread_name; | ||||
|     } | ||||
|  | ||||
|     /* Pickup the thread's current state.  */ | ||||
|     if (state != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *state =  thread_ptr -> tx_thread_state; | ||||
|     } | ||||
|  | ||||
|     /* Pickup the number of times the thread has been scheduled.  */ | ||||
|     if (run_count != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *run_count =  thread_ptr -> tx_thread_run_count; | ||||
|     } | ||||
|  | ||||
|     /* Pickup the thread's priority.  */ | ||||
|     if (priority != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *priority =  thread_ptr -> tx_thread_user_priority; | ||||
|     } | ||||
|  | ||||
|     /* Pickup the thread's preemption-threshold.  */ | ||||
|     if (preemption_threshold != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *preemption_threshold =  thread_ptr -> tx_thread_user_preempt_threshold; | ||||
|     } | ||||
|  | ||||
|     /* Pickup the thread's current time-slice.  */ | ||||
|     if (time_slice != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *time_slice =  thread_ptr -> tx_thread_time_slice; | ||||
|     } | ||||
|  | ||||
|     /* Pickup the next created thread.  */ | ||||
|     if (next_thread != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *next_thread =  thread_ptr -> tx_thread_created_next; | ||||
|     } | ||||
|  | ||||
|     /* Pickup the next thread suspended.  */ | ||||
|     if (next_suspended_thread != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *next_suspended_thread =  thread_ptr -> tx_thread_suspended_next; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										456
									
								
								Middlewares/ST/threadx/common/src/tx_thread_initialize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										456
									
								
								Middlewares/ST/threadx/common/src/tx_thread_initialize.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,456 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| #ifndef TX_MISRA_ENABLE | ||||
| #define TX_THREAD_INIT | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_initialize.h" | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /* Define the pointer that contains the system stack pointer.  This is | ||||
|    utilized when control returns from a thread to the system to reset the | ||||
|    current stack.  This is setup in the low-level initialization function. */ | ||||
|  | ||||
| VOID *          _tx_thread_system_stack_ptr; | ||||
|  | ||||
|  | ||||
| /* Define the current thread pointer.  This variable points to the currently | ||||
|    executing thread.  If this variable is NULL, no thread is executing.  */ | ||||
|  | ||||
| TX_THREAD *     _tx_thread_current_ptr; | ||||
|  | ||||
|  | ||||
| /* Define the variable that holds the next thread to execute.  It is important | ||||
|    to remember that this is not necessarily equal to the current thread  | ||||
|    pointer.  */ | ||||
|  | ||||
| TX_THREAD *     _tx_thread_execute_ptr; | ||||
|  | ||||
|  | ||||
| /* Define the head pointer of the created thread list.  */ | ||||
|  | ||||
| TX_THREAD *     _tx_thread_created_ptr; | ||||
|  | ||||
|  | ||||
| /* Define the variable that holds the number of created threads. */ | ||||
|  | ||||
| ULONG           _tx_thread_created_count; | ||||
|  | ||||
|  | ||||
| /* Define the current state variable.  When this value is 0, a thread | ||||
|    is executing or the system is idle.  Other values indicate that  | ||||
|    interrupt or initialization processing is active.  This variable is | ||||
|    initialized to TX_INITIALIZE_IN_PROGRESS to indicate initialization is | ||||
|    active.  */ | ||||
|  | ||||
| volatile ULONG  _tx_thread_system_state =  TX_INITIALIZE_IN_PROGRESS; | ||||
|  | ||||
|  | ||||
| /* Define the 32-bit priority bit-maps. There is one priority bit map for each | ||||
|    32 priority levels supported. If only 32 priorities are supported there is  | ||||
|    only one bit map. Each bit within a priority bit map represents that one  | ||||
|    or more threads at the associated thread priority are ready.  */ | ||||
|  | ||||
| ULONG           _tx_thread_priority_maps[TX_MAX_PRIORITIES/32]; | ||||
|  | ||||
|  | ||||
| /* Define the priority map active bit map that specifies which of the previously  | ||||
|    defined priority maps have something set. This is only necessary if more than  | ||||
|    32 priorities are supported.  */ | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
| ULONG           _tx_thread_priority_map_active; | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #ifndef TX_DISABLE_PREEMPTION_THRESHOLD | ||||
|  | ||||
| /* Define the 32-bit preempt priority bit maps.  There is one preempt bit map  | ||||
|    for each 32 priority levels supported. If only 32 priorities are supported  | ||||
|    there is only one bit map. Each set set bit corresponds to a preempted priority  | ||||
|    level that had preemption-threshold active to protect against preemption of a  | ||||
|    range of relatively higher priority threads.  */ | ||||
|  | ||||
| ULONG           _tx_thread_preempted_maps[TX_MAX_PRIORITIES/32]; | ||||
|  | ||||
|  | ||||
| /* Define the preempt map active bit map that specifies which of the previously  | ||||
|    defined preempt maps have something set. This is only necessary if more than  | ||||
|    32 priorities are supported.  */ | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
| ULONG           _tx_thread_preempted_map_active; | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| /* Define the variable that holds the highest priority group ready for  | ||||
|    execution.  It is important to note that this is not necessarily the same | ||||
|    as the priority of the thread pointed to by _tx_execute_thread.  */ | ||||
|  | ||||
| UINT            _tx_thread_highest_priority; | ||||
|  | ||||
|  | ||||
| /* Define the array of thread pointers.  Each entry represents the threads that | ||||
|    are ready at that priority group.  For example, index 10 in this array | ||||
|    represents the first thread ready at priority 10.  If this entry is NULL, | ||||
|    no threads are ready at that priority.  */ | ||||
|  | ||||
| TX_THREAD *     _tx_thread_priority_list[TX_MAX_PRIORITIES]; | ||||
|  | ||||
|  | ||||
| /* Define the global preempt disable variable.  If this is non-zero, preemption is | ||||
|    disabled.  It is used internally by ThreadX to prevent preemption of a thread in  | ||||
|    the middle of a service that is resuming or suspending another thread.  */ | ||||
|  | ||||
| volatile UINT   _tx_thread_preempt_disable; | ||||
|  | ||||
|  | ||||
| /* Define the global function pointer for mutex cleanup on thread completion or  | ||||
|    termination. This pointer is setup during mutex initialization.  */ | ||||
|  | ||||
| VOID            (*_tx_thread_mutex_release)(TX_THREAD *thread_ptr); | ||||
|  | ||||
|  | ||||
| /* Define the global build options variable.  This contains a bit map representing | ||||
|    how the ThreadX library was built. The following are the bit field definitions: | ||||
|  | ||||
|                     Bit(s)                   Meaning | ||||
|  | ||||
|                     31                  TX_NOT_INTERRUPTABLE defined | ||||
|                     30                  TX_INLINE_THREAD_RESUME_SUSPEND define | ||||
|                     29-24               Priority groups 1  -> 32 priorities | ||||
|                                                         2  -> 64 priorities | ||||
|                                                         3  -> 96 priorities | ||||
|  | ||||
|                                                         ... | ||||
|  | ||||
|                                                         32 -> 1024 priorities | ||||
|                     23                  TX_TIMER_PROCESS_IN_ISR defined | ||||
|                     22                  TX_REACTIVATE_INLINE defined | ||||
|                     21                  TX_DISABLE_STACK_FILLING defined | ||||
|                     20                  TX_ENABLE_STACK_CHECKING defined | ||||
|                     19                  TX_DISABLE_PREEMPTION_THRESHOLD defined | ||||
|                     18                  TX_DISABLE_REDUNDANT_CLEARING defined | ||||
|                     17                  TX_DISABLE_NOTIFY_CALLBACKS defined | ||||
|                     16                  TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO defined | ||||
|                     15                  TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO defined | ||||
|                     14                  TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO defined | ||||
|                     13                  TX_MUTEX_ENABLE_PERFORMANCE_INFO defined | ||||
|                     12                  TX_QUEUE_ENABLE_PERFORMANCE_INFO defined | ||||
|                     11                  TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO defined | ||||
|                     10                  TX_THREAD_ENABLE_PERFORMANCE_INFO defined | ||||
|                     9                   TX_TIMER_ENABLE_PERFORMANCE_INFO defined | ||||
|                     8                   TX_ENABLE_EVENT_TRACE defined | ||||
|                     7                   TX_ENABLE_EXECUTION_CHANGE_NOTIFY defined | ||||
|                     6-0                 Port Specific   */ | ||||
|  | ||||
| ULONG           _tx_build_options; | ||||
|  | ||||
|  | ||||
| #if defined(TX_ENABLE_STACK_CHECKING) || defined(TX_PORT_THREAD_STACK_ERROR_HANDLING) | ||||
|  | ||||
| /* Define the global function pointer for stack error handling. If a stack error is  | ||||
|    detected and the application has registered a stack error handler, it will be  | ||||
|    called via this function pointer.  */ | ||||
|  | ||||
| VOID            (*_tx_thread_application_stack_error_handler)(TX_THREAD *thread_ptr); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
| /* Define the total number of thread resumptions. Each time a thread enters the | ||||
|    ready state this variable is incremented.  */ | ||||
|  | ||||
| ULONG           _tx_thread_performance_resume_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of thread suspensions. Each time a thread enters a  | ||||
|    suspended state this variable is incremented.  */ | ||||
|  | ||||
| ULONG           _tx_thread_performance_suspend_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of solicited thread preemptions. Each time a thread is  | ||||
|    preempted by directly calling a ThreadX service, this variable is incremented.  */ | ||||
|  | ||||
| ULONG           _tx_thread_performance_solicited_preemption_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of interrupt thread preemptions. Each time a thread is  | ||||
|    preempted as a result of an ISR calling a ThreadX service, this variable is  | ||||
|    incremented.  */ | ||||
|  | ||||
| ULONG           _tx_thread_performance_interrupt_preemption_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of priority inversions. Each time a thread is blocked by | ||||
|    a mutex owned by a lower-priority thread, this variable is incremented.  */ | ||||
|  | ||||
| ULONG           _tx_thread_performance_priority_inversion_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of time-slices.  Each time a time-slice operation is  | ||||
|    actually performed (another thread is setup for running) this variable is  | ||||
|    incremented.  */ | ||||
|  | ||||
| ULONG           _tx_thread_performance_time_slice_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of thread relinquish operations.  Each time a thread  | ||||
|    relinquish operation is actually performed (another thread is setup for running) | ||||
|    this variable is incremented.  */ | ||||
|  | ||||
| ULONG           _tx_thread_performance_relinquish_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of thread timeouts. Each time a thread has a  | ||||
|    timeout this variable is incremented.  */ | ||||
|  | ||||
| ULONG           _tx_thread_performance_timeout_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of thread wait aborts. Each time a thread's suspension  | ||||
|    is lifted by the tx_thread_wait_abort call this variable is incremented.  */ | ||||
|  | ||||
| ULONG           _tx_thread_performance_wait_abort_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of idle system thread returns. Each time a thread returns to  | ||||
|    an idle system (no other thread is ready to run) this variable is incremented.  */ | ||||
|  | ||||
| ULONG           _tx_thread_performance_idle_return_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of non-idle system thread returns. Each time a thread returns to  | ||||
|    a non-idle system (another thread is ready to run) this variable is incremented.  */ | ||||
|  | ||||
| ULONG           _tx_thread_performance_non_idle_return_count; | ||||
|  | ||||
|  | ||||
| /* Define the last TX_THREAD_EXECUTE_LOG_SIZE threads scheduled in ThreadX. This  | ||||
|    is a circular list, where the index points to the oldest entry.  */ | ||||
|  | ||||
| ULONG           _tx_thread_performance__execute_log_index; | ||||
| TX_THREAD *     _tx_thread_performance_execute_log[TX_THREAD_EXECUTE_LOG_SIZE]; | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /* Define special string.  */ | ||||
|  | ||||
| #ifndef TX_MISRA_ENABLE | ||||
| const CHAR _tx_thread_special_string[] =  | ||||
|   "G-ML-EL-ML-BL-DL-BL-GB-GL-M-D-DL-GZ-KH-EL-CM-NH-HA-GF-DD-JC-YZ-CT-AT-DW-USA-CA-SD-SDSU"; | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_initialize                               PORTABLE C      */ | ||||
| /*                                                           6.1.9        */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function initializes the various control data structures for   */ | ||||
| /*    the thread control component.                                       */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_initialize_high_level         High level initialization         */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*  06-02-2021     Yuxin Zhou               Modified comment(s), added    */ | ||||
| /*                                            Execution Profile support,  */ | ||||
| /*                                            resulting in version 6.1.7  */ | ||||
| /*  10-15-2021     Yuxin Zhou               Modified comment(s), improved */ | ||||
| /*                                            stack check error handling, */ | ||||
| /*                                            resulting in version 6.1.9  */    | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_thread_initialize(VOID) | ||||
| { | ||||
|  | ||||
|     /* Note: the system stack pointer and the system state variables are  | ||||
|        initialized by the low and high-level initialization functions, | ||||
|        respectively.  */ | ||||
|  | ||||
| #ifndef TX_DISABLE_REDUNDANT_CLEARING | ||||
|  | ||||
|     /* Set current thread pointer to NULL.  */ | ||||
|     TX_THREAD_SET_CURRENT(TX_NULL) | ||||
|  | ||||
|     /* Initialize the execute thread pointer to NULL.  */ | ||||
|     _tx_thread_execute_ptr =  TX_NULL; | ||||
|  | ||||
|     /* Initialize the priority information.  */ | ||||
|     TX_MEMSET(&_tx_thread_priority_maps[0], 0, (sizeof(_tx_thread_priority_maps))); | ||||
|  | ||||
| #ifndef TX_DISABLE_PREEMPTION_THRESHOLD | ||||
|     TX_MEMSET(&_tx_thread_preempted_maps[0], 0, (sizeof(_tx_thread_preempted_maps))); | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
|     /* Setup the highest priority variable to the max, indicating no thread is currently | ||||
|        ready.  */ | ||||
|     _tx_thread_highest_priority =  ((UINT) TX_MAX_PRIORITIES); | ||||
|  | ||||
|  | ||||
| #ifndef TX_DISABLE_REDUNDANT_CLEARING | ||||
|  | ||||
|     /* Initialize the array of priority head pointers.  */ | ||||
|     TX_MEMSET(&_tx_thread_priority_list[0], 0, (sizeof(_tx_thread_priority_list))); | ||||
|  | ||||
|     /* Initialize the head pointer of the created threads list and the | ||||
|        number of threads created.  */ | ||||
|     _tx_thread_created_ptr =        TX_NULL; | ||||
|     _tx_thread_created_count =      TX_EMPTY; | ||||
|  | ||||
|     /* Clear the global preempt disable variable.  */ | ||||
|     _tx_thread_preempt_disable =    ((UINT) 0); | ||||
|  | ||||
|     /* Initialize the thread mutex release function pointer.  */ | ||||
|     _tx_thread_mutex_release =      TX_NULL; | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|  | ||||
|     /* Clear application registered stack error handler.  */ | ||||
|     _tx_thread_application_stack_error_handler =  TX_NULL; | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Clear performance counters.  */ | ||||
|     _tx_thread_performance_resume_count =                ((ULONG) 0); | ||||
|     _tx_thread_performance_suspend_count =               ((ULONG) 0); | ||||
|     _tx_thread_performance_solicited_preemption_count =  ((ULONG) 0); | ||||
|     _tx_thread_performance_interrupt_preemption_count =  ((ULONG) 0); | ||||
|     _tx_thread_performance_priority_inversion_count =    ((ULONG) 0); | ||||
|     _tx_thread_performance_time_slice_count =            ((ULONG) 0); | ||||
|     _tx_thread_performance_relinquish_count =            ((ULONG) 0); | ||||
|     _tx_thread_performance_timeout_count =               ((ULONG) 0); | ||||
|     _tx_thread_performance_wait_abort_count =            ((ULONG) 0); | ||||
|     _tx_thread_performance_idle_return_count =           ((ULONG) 0); | ||||
|     _tx_thread_performance_non_idle_return_count =       ((ULONG) 0); | ||||
|  | ||||
|     /* Initialize the execute thread log.  */ | ||||
|     TX_MEMSET(&_tx_thread_performance_execute_log[0], 0, (sizeof(_tx_thread_performance_execute_log))); | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
|     /* Setup the build options flag. This is used to identify how the ThreadX library was constructed.  */ | ||||
|     _tx_build_options =  _tx_build_options  | ||||
|                             | (((ULONG) (TX_MAX_PRIORITIES/32)) << 24)  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|                             | (((ULONG) 1) << 31) | ||||
| #endif | ||||
| #ifdef TX_INLINE_THREAD_RESUME_SUSPEND | ||||
|                             | (((ULONG) 1) << 30) | ||||
| #endif | ||||
| #ifdef TX_TIMER_PROCESS_IN_ISR | ||||
|                             | (((ULONG) 1) << 23) | ||||
| #endif | ||||
| #ifdef TX_REACTIVATE_INLINE | ||||
|                             | (((ULONG) 1) << 22) | ||||
| #endif | ||||
| #ifdef TX_DISABLE_STACK_FILLING | ||||
|                             | (((ULONG) 1) << 21) | ||||
| #endif | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|                             | (((ULONG) 1) << 20) | ||||
| #endif | ||||
| #ifdef TX_DISABLE_PREEMPTION_THRESHOLD | ||||
|                             | (((ULONG) 1) << 19) | ||||
| #endif | ||||
| #ifdef TX_DISABLE_REDUNDANT_CLEARING | ||||
|                             | (((ULONG) 1) << 18) | ||||
| #endif | ||||
| #ifdef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|                             | (((ULONG) 1) << 17) | ||||
| #endif | ||||
| #ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO | ||||
|                             | (((ULONG) 1) << 16) | ||||
| #endif | ||||
| #ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO | ||||
|                             | (((ULONG) 1) << 15) | ||||
| #endif | ||||
| #ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO | ||||
|                             | (((ULONG) 1) << 14) | ||||
| #endif | ||||
| #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO | ||||
|                             | (((ULONG) 1) << 13) | ||||
| #endif | ||||
| #ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO | ||||
|                             | (((ULONG) 1) << 12) | ||||
| #endif | ||||
| #ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO | ||||
|                             | (((ULONG) 1) << 11) | ||||
| #endif | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|                             | (((ULONG) 1) << 10) | ||||
| #endif | ||||
| #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO | ||||
|                             | (((ULONG) 1) << 9) | ||||
| #endif | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|                             | (((ULONG) 1) << 8) | ||||
| #endif | ||||
| #if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) | ||||
|                             | (((ULONG) 1) << 7) | ||||
| #endif | ||||
| #if TX_PORT_SPECIFIC_BUILD_OPTIONS != 0 | ||||
|                             | TX_PORT_SPECIFIC_BUILD_OPTIONS | ||||
| #endif | ||||
|                             ; | ||||
| } | ||||
|  | ||||
							
								
								
									
										282
									
								
								Middlewares/ST/threadx/common/src/tx_thread_preemption_change.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										282
									
								
								Middlewares/ST/threadx/common/src/tx_thread_preemption_change.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,282 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_preemption_change                        PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function processes preemption-threshold change requests.  The  */ | ||||
| /*    previous preemption is returned to the caller.  If the new request  */ | ||||
| /*    allows a higher priority thread to execute, preemption takes place  */ | ||||
| /*    inside of this function.                                            */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                            Pointer to thread             */ | ||||
| /*    new_threshold                         New preemption threshold      */ | ||||
| /*    old_threshold                         Old preemption threshold      */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Service return status         */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check       Check for preemption          */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_thread_preemption_change(TX_THREAD *thread_ptr, UINT new_threshold, UINT *old_threshold) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| #ifndef TX_DISABLE_PREEMPTION_THRESHOLD | ||||
| ULONG       priority_bit; | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
| UINT        map_index; | ||||
| #endif | ||||
| #endif | ||||
| UINT        status; | ||||
|  | ||||
|  | ||||
|     /* Default status to success.  */ | ||||
|     status =  TX_SUCCESS; | ||||
|  | ||||
| #ifdef TX_DISABLE_PREEMPTION_THRESHOLD | ||||
|  | ||||
|     /* Only allow 0 (disable all preemption) and returning preemption-threshold to the | ||||
|        current thread priority if preemption-threshold is disabled. All other threshold | ||||
|        values are converted to 0.  */ | ||||
|     if (thread_ptr -> tx_thread_user_priority != new_threshold) | ||||
|     { | ||||
|  | ||||
|         /* Is the new threshold zero?  */ | ||||
|         if (new_threshold != ((UINT) 0)) | ||||
|         { | ||||
|  | ||||
|             /* Convert the new threshold to disable all preemption, since preemption-threshold is | ||||
|                not supported.  */ | ||||
|             new_threshold =  ((UINT) 0); | ||||
|         } | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     /* Lockout interrupts while the thread is being resumed.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_PREEMPTION_CHANGE, thread_ptr, new_threshold, thread_ptr -> tx_thread_preempt_threshold, thread_ptr -> tx_thread_state, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_THREAD_PREEMPTION_CHANGE_INSERT | ||||
|  | ||||
|     /* Determine if the new threshold is greater than the current user priority.  */ | ||||
|     if (new_threshold > thread_ptr -> tx_thread_user_priority) | ||||
|     { | ||||
|  | ||||
|         /* Return error.  */ | ||||
|         status =  TX_THRESH_ERROR; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
| #ifndef TX_DISABLE_PREEMPTION_THRESHOLD | ||||
|  | ||||
|         /* Determine if the new threshold is the same as the priority.  */ | ||||
|         if (thread_ptr -> tx_thread_user_priority == new_threshold) | ||||
|         { | ||||
|  | ||||
|             /* Determine if this thread is at the head of the list.  */ | ||||
|             if (_tx_thread_priority_list[thread_ptr -> tx_thread_priority] == thread_ptr) | ||||
|             { | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|  | ||||
|                 /* Calculate the index into the bit map array.  */ | ||||
|                 map_index =  (thread_ptr -> tx_thread_priority)/((UINT) 32); | ||||
| #endif | ||||
|  | ||||
|                 /* Yes, this thread is at the front of the list.  Make sure | ||||
|                    the preempted bit is cleared for this thread.  */ | ||||
|                 TX_MOD32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit) | ||||
|                 _tx_thread_preempted_maps[MAP_INDEX] =  _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit)); | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|  | ||||
|                 /* Determine if there are any other bits set in this preempt map.  */ | ||||
|                 if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0)) | ||||
|                 { | ||||
|  | ||||
|                     /* No, clear the active bit to signify this preempt map has nothing set.  */ | ||||
|                     TX_DIV32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit) | ||||
|                     _tx_thread_preempted_map_active =  _tx_thread_preempted_map_active & (~(priority_bit)); | ||||
|                 } | ||||
| #endif | ||||
|             } | ||||
|         } | ||||
| #endif | ||||
|  | ||||
|         /* Return the user's preemption-threshold.   */ | ||||
|         *old_threshold =  thread_ptr -> tx_thread_user_preempt_threshold; | ||||
|  | ||||
|         /* Setup the new threshold.  */ | ||||
|         thread_ptr -> tx_thread_user_preempt_threshold =  new_threshold; | ||||
|  | ||||
|         /* Determine if the new threshold represents a higher priority than the priority inheritance threshold.  */ | ||||
|         if (new_threshold < thread_ptr -> tx_thread_inherit_priority) | ||||
|         { | ||||
|  | ||||
|             /* Update the actual preemption-threshold with the new threshold.  */ | ||||
|             thread_ptr -> tx_thread_preempt_threshold =  new_threshold; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Update the actual preemption-threshold with the priority inheritance.  */ | ||||
|             thread_ptr -> tx_thread_preempt_threshold =  thread_ptr -> tx_thread_inherit_priority; | ||||
|         } | ||||
|  | ||||
|         /* Is the thread priority less than the current highest priority?  If not, no preemption is required.  */ | ||||
|         if (_tx_thread_highest_priority < thread_ptr -> tx_thread_priority) | ||||
|         { | ||||
|  | ||||
|             /* Is the new thread preemption-threshold less than the current highest priority?  If not, no preemption is required.  */ | ||||
|             if (_tx_thread_highest_priority < new_threshold) | ||||
|             { | ||||
|  | ||||
|                 /* If the current execute pointer is the same at this thread, preemption needs to take place.  */ | ||||
|                 if (_tx_thread_execute_ptr == thread_ptr) | ||||
|                 { | ||||
|  | ||||
|                     /* Preemption needs to take place.  */ | ||||
|  | ||||
| #ifndef TX_DISABLE_PREEMPTION_THRESHOLD | ||||
|  | ||||
|                     /* Determine if this thread has preemption threshold set.  */ | ||||
|                     if (thread_ptr -> tx_thread_preempt_threshold != thread_ptr -> tx_thread_priority) | ||||
|                     { | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|  | ||||
|                         /* Calculate the index into the bit map array.  */ | ||||
|                         map_index =  (thread_ptr -> tx_thread_priority)/((UINT) 32); | ||||
|  | ||||
|                         /* Set the active bit to remember that the preempt map has something set.  */ | ||||
|                         TX_DIV32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit) | ||||
|                         _tx_thread_preempted_map_active =  _tx_thread_preempted_map_active | priority_bit; | ||||
| #endif | ||||
|  | ||||
|                         /* Remember that this thread was preempted by a thread above the thread's threshold.  */ | ||||
|                         TX_MOD32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit) | ||||
|                         _tx_thread_preempted_maps[MAP_INDEX] =  _tx_thread_preempted_maps[MAP_INDEX] | priority_bit; | ||||
|                     } | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                     /* Determine if the caller is an interrupt or from a thread.  */ | ||||
|                     if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0)) | ||||
|                     { | ||||
|  | ||||
|                         /* Caller is a thread, so this is a solicited preemption.  */ | ||||
|                         _tx_thread_performance_solicited_preemption_count++; | ||||
|  | ||||
|                         /* Increment the thread's solicited preemption counter.  */ | ||||
|                         thread_ptr -> tx_thread_performance_solicited_preemption_count++; | ||||
|                     } | ||||
|  | ||||
|                     /* Remember the thread that preempted this thread.  */ | ||||
|                     thread_ptr -> tx_thread_performance_last_preempting_thread =  _tx_thread_priority_list[_tx_thread_highest_priority]; | ||||
|  | ||||
|                     /* Is the execute pointer different?  */ | ||||
|                     if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) | ||||
|                     { | ||||
|  | ||||
|                         /* Move to next entry.  */ | ||||
|                         _tx_thread_performance__execute_log_index++; | ||||
|  | ||||
|                         /* Check for wrap condition.  */ | ||||
|                         if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) | ||||
|                         { | ||||
|  | ||||
|                             /* Set the index to the beginning.  */ | ||||
|                             _tx_thread_performance__execute_log_index =  ((UINT) 0); | ||||
|                         } | ||||
|  | ||||
|                         /* Log the new execute pointer.  */ | ||||
|                         _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] =  _tx_thread_execute_ptr; | ||||
|                     } | ||||
| #endif | ||||
|  | ||||
|                     /* Setup the highest priority thread to execute.  */ | ||||
|                     _tx_thread_execute_ptr =  _tx_thread_priority_list[_tx_thread_highest_priority]; | ||||
|  | ||||
|                     /* Restore interrupts.  */ | ||||
|                     TX_RESTORE | ||||
|  | ||||
|                     /* Check for preemption.  */ | ||||
|                     _tx_thread_system_preempt_check(); | ||||
|  | ||||
|                     /* Disable interrupts.  */ | ||||
|                     TX_DISABLE | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										287
									
								
								Middlewares/ST/threadx/common/src/tx_thread_priority_change.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										287
									
								
								Middlewares/ST/threadx/common/src/tx_thread_priority_change.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,287 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_priority_change                          PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function changes the priority of the specified thread.  It     */ | ||||
| /*    also returns the old priority and handles preemption if the calling */ | ||||
| /*    thread is currently executing and the priority change results in a  */ | ||||
| /*    higher priority thread ready for execution.                         */ | ||||
| /*                                                                        */ | ||||
| /*    Note: the preemption threshold is automatically changed to the new  */ | ||||
| /*    priority.                                                           */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                            Pointer to thread to suspend  */ | ||||
| /*    new_priority                          New thread priority           */ | ||||
| /*    old_priority                          Old thread priority           */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Completion status             */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread                     */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*    _tx_thread_system_suspend         Suspend thread                    */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     William E. Lamie         Modified comment(s), and      */ | ||||
| /*                                            change thread state from    */ | ||||
| /*                                            TX_SUSPENDED to             */ | ||||
| /*                                            TX_PRIORITY_CHANGE before   */ | ||||
| /*                                            calling                     */ | ||||
| /*                                            _tx_thread_system_suspend,  */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_thread_priority_change(TX_THREAD *thread_ptr, UINT new_priority, UINT *old_priority) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *execute_ptr; | ||||
| TX_THREAD       *next_execute_ptr; | ||||
| UINT            original_priority; | ||||
|  | ||||
|  | ||||
|     /* Lockout interrupts while the thread is being suspended.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Save the previous priority.  */ | ||||
|     *old_priority =  thread_ptr -> tx_thread_user_priority; | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_PRIORITY_CHANGE, thread_ptr, new_priority, thread_ptr -> tx_thread_priority, thread_ptr -> tx_thread_state, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_THREAD_PRIORITY_CHANGE_INSERT | ||||
|  | ||||
|     /* Determine if this thread is currently ready.  */ | ||||
|     if (thread_ptr -> tx_thread_state != TX_READY) | ||||
|     { | ||||
|  | ||||
|         /* Setup the user priority and threshold in the thread's control | ||||
|            block.  */ | ||||
|         thread_ptr -> tx_thread_user_priority =               new_priority; | ||||
|         thread_ptr -> tx_thread_user_preempt_threshold =      new_priority; | ||||
|  | ||||
|         /* Determine if the actual thread priority should be setup, which is the | ||||
|            case if the new priority is higher than the priority inheritance.  */ | ||||
|         if (new_priority < thread_ptr -> tx_thread_inherit_priority) | ||||
|         { | ||||
|  | ||||
|             /* Change thread priority to the new user's priority.  */ | ||||
|             thread_ptr -> tx_thread_priority =           new_priority; | ||||
|             thread_ptr -> tx_thread_preempt_threshold =  new_priority; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Change thread priority to the priority inheritance.  */ | ||||
|             thread_ptr -> tx_thread_priority =           thread_ptr -> tx_thread_inherit_priority; | ||||
|             thread_ptr -> tx_thread_preempt_threshold =  thread_ptr -> tx_thread_inherit_priority; | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Set the state to priority change.  */ | ||||
|         thread_ptr -> tx_thread_state =    TX_PRIORITY_CHANGE; | ||||
|  | ||||
|         /* Pickup the next thread to execute.  */ | ||||
|         execute_ptr =  _tx_thread_execute_ptr; | ||||
|  | ||||
|         /* Save the original priority.  */ | ||||
|         original_priority =  thread_ptr -> tx_thread_priority; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Increment the preempt disable flag.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Call actual non-interruptable thread suspension routine.  */ | ||||
|         _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0)); | ||||
|  | ||||
|         /* At this point, the preempt disable flag is still set, so we still have | ||||
|            protection against all preemption.  */ | ||||
|  | ||||
|         /* Setup the new priority for this thread.  */ | ||||
|         thread_ptr -> tx_thread_user_priority =           new_priority; | ||||
|         thread_ptr -> tx_thread_user_preempt_threshold =  new_priority; | ||||
|  | ||||
|         /* Determine if the actual thread priority should be setup, which is the | ||||
|            case if the new priority is higher than the priority inheritance.  */ | ||||
|         if (new_priority < thread_ptr -> tx_thread_inherit_priority) | ||||
|         { | ||||
|  | ||||
|             /* Change thread priority to the new user's priority.  */ | ||||
|             thread_ptr -> tx_thread_priority =           new_priority; | ||||
|             thread_ptr -> tx_thread_preempt_threshold =  new_priority; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Change thread priority to the priority inheritance.  */ | ||||
|             thread_ptr -> tx_thread_priority =           thread_ptr -> tx_thread_inherit_priority; | ||||
|             thread_ptr -> tx_thread_preempt_threshold =  thread_ptr -> tx_thread_inherit_priority; | ||||
|         } | ||||
|  | ||||
|         /* Resume the thread with the new priority.  */ | ||||
|         _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
| #else | ||||
|  | ||||
|         /* Increment the preempt disable flag by 2 to prevent system suspend from | ||||
|            returning to the system.  */ | ||||
|         _tx_thread_preempt_disable =  _tx_thread_preempt_disable + ((UINT) 3); | ||||
|  | ||||
|         /* Set the suspending flag. */ | ||||
|         thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|         /* Setup the timeout period.  */ | ||||
|         thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  ((ULONG) 0); | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* The thread is ready and must first be removed from the list.  Call the | ||||
|            system suspend function to accomplish this.  */ | ||||
|         _tx_thread_system_suspend(thread_ptr); | ||||
|  | ||||
|         /* At this point, the preempt disable flag is still set, so we still have | ||||
|            protection against all preemption.  */ | ||||
|  | ||||
|         /* Setup the new priority for this thread.  */ | ||||
|         thread_ptr -> tx_thread_user_priority =           new_priority; | ||||
|         thread_ptr -> tx_thread_user_preempt_threshold =  new_priority; | ||||
|  | ||||
|         /* Determine if the actual thread priority should be setup, which is the | ||||
|            case if the new priority is higher than the priority inheritance.  */ | ||||
|         if (new_priority < thread_ptr -> tx_thread_inherit_priority) | ||||
|         { | ||||
|  | ||||
|             /* Change thread priority to the new user's priority.  */ | ||||
|             thread_ptr -> tx_thread_priority =           new_priority; | ||||
|             thread_ptr -> tx_thread_preempt_threshold =  new_priority; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Change thread priority to the priority inheritance.  */ | ||||
|             thread_ptr -> tx_thread_priority =           thread_ptr -> tx_thread_inherit_priority; | ||||
|             thread_ptr -> tx_thread_preempt_threshold =  thread_ptr -> tx_thread_inherit_priority; | ||||
|         } | ||||
|  | ||||
|         /* Resume the thread with the new priority.  */ | ||||
|         _tx_thread_system_resume(thread_ptr); | ||||
|  | ||||
|         /* Disable interrupts.  */ | ||||
|         TX_DISABLE | ||||
| #endif | ||||
|  | ||||
|         /* Decrement the preempt disable flag.  */ | ||||
|         _tx_thread_preempt_disable--; | ||||
|  | ||||
|         /* Pickup the next thread to execute.  */ | ||||
|         next_execute_ptr =  _tx_thread_execute_ptr; | ||||
|  | ||||
|         /* Determine if this thread is not the next thread to execute.  */ | ||||
|         if (thread_ptr != next_execute_ptr) | ||||
|         { | ||||
|  | ||||
|             /* Make sure the thread is still ready.  */ | ||||
|             if (thread_ptr -> tx_thread_state == TX_READY) | ||||
|             { | ||||
|  | ||||
|                 /* Now check and see if this thread has an equal or higher priority.  */ | ||||
|                 if (thread_ptr -> tx_thread_priority <= next_execute_ptr -> tx_thread_priority) | ||||
|                 { | ||||
|  | ||||
|                     /* Now determine if this thread was the previously executing thread.  */ | ||||
|                     if (thread_ptr == execute_ptr) | ||||
|                     { | ||||
|  | ||||
|                         /* Yes, this thread was previously executing before we temporarily suspended and resumed | ||||
|                            it in order to change the priority. A lower or same priority thread cannot be the next thread | ||||
|                            to execute in this case since this thread really didn't suspend.  Simply reset the execute | ||||
|                            pointer to this thread.  */ | ||||
|                         _tx_thread_execute_ptr =  thread_ptr; | ||||
|  | ||||
|                         /* Determine if we moved to a lower priority. If so, move the thread to the front of its priority list.  */ | ||||
|                         if (original_priority < new_priority) | ||||
|                         { | ||||
|  | ||||
|                             /* Ensure that this thread is placed at the front of the priority list.  */ | ||||
|                             _tx_thread_priority_list[thread_ptr -> tx_thread_priority] =  thread_ptr; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Check for preemption.  */ | ||||
|         _tx_thread_system_preempt_check(); | ||||
|     } | ||||
|  | ||||
|     /* Return success if we get here!  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										171
									
								
								Middlewares/ST/threadx/common/src/tx_thread_relinquish.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								Middlewares/ST/threadx/common/src/tx_thread_relinquish.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,171 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #ifndef TX_NO_TIMER | ||||
| #include "tx_timer.h" | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_relinquish                               PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function moves the currently executing thread to the end of    */ | ||||
| /*    the list of threads ready at the same priority. If no other threads */ | ||||
| /*    of the same or higher priority are ready, this function simply      */ | ||||
| /*    returns.                                                            */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_return              Return to the system          */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_thread_relinquish(VOID) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| UINT            priority; | ||||
| TX_THREAD       *thread_ptr; | ||||
|  | ||||
|  | ||||
|     /* Pickup thread pointer.  */ | ||||
|     TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|  | ||||
|     /* Check this thread's stack.  */ | ||||
|     TX_THREAD_STACK_CHECK(thread_ptr) | ||||
| #endif | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifndef TX_NO_TIMER | ||||
|  | ||||
|     /* Reset time slice for current thread.  */ | ||||
|     _tx_timer_time_slice =  thread_ptr -> tx_thread_new_time_slice; | ||||
| #endif | ||||
|  | ||||
|     /* Pickup the thread's priority.  */ | ||||
|     priority =  thread_ptr -> tx_thread_priority; | ||||
|  | ||||
|     /* Determine if there is another thread at the same priority.  */ | ||||
|     if (thread_ptr -> tx_thread_ready_next != thread_ptr) | ||||
|     { | ||||
|  | ||||
|         /* Yes, there is another thread at this priority, make it the highest at | ||||
|            this priority level.  */ | ||||
|         _tx_thread_priority_list[priority] =  thread_ptr -> tx_thread_ready_next; | ||||
|  | ||||
|         /* Mark the new thread as the one to execute.  */ | ||||
|         _tx_thread_execute_ptr = thread_ptr -> tx_thread_ready_next; | ||||
|     } | ||||
|  | ||||
|     /* Determine if there is a higher-priority thread ready.  */ | ||||
|     if (_tx_thread_highest_priority < priority) | ||||
|     { | ||||
|  | ||||
|         /* Yes, there is a higher priority thread ready to execute.  Make | ||||
|            it visible to the thread scheduler.  */ | ||||
|         _tx_thread_execute_ptr =  _tx_thread_priority_list[_tx_thread_highest_priority]; | ||||
|  | ||||
|         /* No need to clear the preempted bit in this case, since the currently running | ||||
|            thread must already have its preempted bit clear.  */ | ||||
|     } | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RELINQUISH, &thread_ptr, TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), 0, 0, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_THREAD_RELINQUISH_INSERT | ||||
|  | ||||
|     /* Restore previous interrupt posture.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Determine if this thread needs to return to the system.  */ | ||||
|     if (_tx_thread_execute_ptr != thread_ptr) | ||||
|     { | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|         /* Increment the number of thread relinquishes.  */ | ||||
|         thread_ptr -> tx_thread_performance_relinquish_count++; | ||||
|  | ||||
|         /* Increment the total number of thread relinquish operations.  */ | ||||
|         _tx_thread_performance_relinquish_count++; | ||||
|  | ||||
|         /* Increment the non-idle return count.  */ | ||||
|         _tx_thread_performance_non_idle_return_count++; | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|  | ||||
|         /* Pickup the next execute pointer.  */ | ||||
|         thread_ptr =  _tx_thread_execute_ptr; | ||||
|  | ||||
|         /* Check this thread's stack.  */ | ||||
|         TX_THREAD_STACK_CHECK(thread_ptr) | ||||
| #endif | ||||
|  | ||||
|         /* Transfer control to the system so the scheduler can execute | ||||
|            the next thread.  */ | ||||
|         _tx_thread_system_return(); | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										165
									
								
								Middlewares/ST/threadx/common/src/tx_thread_reset.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								Middlewares/ST/threadx/common/src/tx_thread_reset.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_reset                                    PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function prepares the thread to run again from the entry       */ | ||||
| /*    point specified during thread creation. The application must        */ | ||||
| /*    call tx_thread_resume after this call completes for the thread      */ | ||||
| /*    to actually run.                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                            Pointer to thread to reset    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Service return status         */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_stack_build                Build initial thread stack    */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_thread_reset(TX_THREAD *thread_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *current_thread; | ||||
| UINT            status; | ||||
|  | ||||
|  | ||||
|     /* Default a successful completion status.  */ | ||||
|     status =  TX_SUCCESS; | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Pickup thread pointer.  */ | ||||
|     TX_THREAD_GET_CURRENT(current_thread) | ||||
|  | ||||
|     /* Check for a call from the current thread, which is not allowed!  */ | ||||
|     if (current_thread == thread_ptr) | ||||
|     { | ||||
|  | ||||
|         /* Thread not completed or terminated - return an error!  */ | ||||
|         status =  TX_NOT_DONE; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Check for proper status of this thread to reset.  */ | ||||
|         if (thread_ptr -> tx_thread_state != TX_COMPLETED) | ||||
|         { | ||||
|  | ||||
|             /* Now check for terminated state.  */ | ||||
|             if (thread_ptr -> tx_thread_state != TX_TERMINATED) | ||||
|             { | ||||
|  | ||||
|                 /* Thread not completed or terminated - return an error!  */ | ||||
|                 status =  TX_NOT_DONE; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Is the request valid?  */ | ||||
|     if (status == TX_SUCCESS) | ||||
|     { | ||||
|  | ||||
|         /* Modify the thread status to prevent additional reset calls.  */ | ||||
|         thread_ptr -> tx_thread_state =  TX_NOT_DONE; | ||||
|  | ||||
|         /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h.  */ | ||||
|         TX_THREAD_RESET_PORT_COMPLETION(thread_ptr) | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
| #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_stack_start, ((UCHAR) TX_STACK_FILL), thread_ptr -> tx_thread_stack_size); | ||||
| #endif | ||||
|  | ||||
|         /* Call the target specific stack frame building routine to build the | ||||
|            thread's initial stack and to setup the actual stack pointer in the | ||||
|            control block.  */ | ||||
|         _tx_thread_stack_build(thread_ptr, _tx_thread_shell_entry); | ||||
|  | ||||
|         /* Disable interrupts.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* Finally, move into a suspended state to allow for the thread to be resumed.  */ | ||||
|         thread_ptr -> tx_thread_state =  TX_SUSPENDED; | ||||
|  | ||||
|         /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|         TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESET, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|         /* Log this kernel call.  */ | ||||
|         TX_EL_THREAD_RESET_INSERT | ||||
|  | ||||
|         /* Log the thread status change.  */ | ||||
|         TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_SUSPENDED) | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return completion status to caller.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										583
									
								
								Middlewares/ST/threadx/common/src/tx_thread_resume.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										583
									
								
								Middlewares/ST/threadx/common/src/tx_thread_resume.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,583 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_initialize.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_resume                                   PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function processes application resume thread services. Actual  */ | ||||
| /*    thread resumption is performed in the core service.                 */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                            Pointer to thread to resume   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Service return status         */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread                     */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_thread_resume(TX_THREAD *thread_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| UINT        status; | ||||
| TX_THREAD   *saved_thread_ptr; | ||||
| UINT        saved_threshold =  ((UINT) 0); | ||||
|  | ||||
| #ifdef TX_INLINE_THREAD_RESUME_SUSPEND | ||||
| UINT            priority; | ||||
| ULONG           priority_bit; | ||||
| TX_THREAD       *head_ptr; | ||||
| TX_THREAD       *tail_ptr; | ||||
| TX_THREAD       *execute_ptr; | ||||
| TX_THREAD       *current_thread; | ||||
| ULONG           combined_flags; | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
| TX_TRACE_BUFFER_ENTRY       *entry_ptr; | ||||
| ULONG                       time_stamp =  ((ULONG) 0); | ||||
| #endif | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
| UINT            map_index; | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|  | ||||
|     /* Check this thread's stack.  */ | ||||
|     TX_THREAD_STACK_CHECK(thread_ptr) | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
|     /* Lockout interrupts while the thread is being resumed.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESUME_API, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&status), 0, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_THREAD_RESUME_INSERT | ||||
|  | ||||
|     /* Determine if the thread is suspended or in the process of suspending. | ||||
|        If so, call the thread resume processing.  */ | ||||
|     if (thread_ptr -> tx_thread_state == TX_SUSPENDED) | ||||
|     { | ||||
|  | ||||
|         /* Determine if the create call is being called from initialization.  */ | ||||
|         if (TX_THREAD_GET_SYSTEM_STATE() >= TX_INITIALIZE_IN_PROGRESS) | ||||
|         { | ||||
|  | ||||
|             /* Yes, this resume call was made from initialization.  */ | ||||
|  | ||||
|             /* Pickup the current thread execute pointer, which corresponds to the | ||||
|                highest priority thread ready to execute.  Interrupt lockout is | ||||
|                not required, since interrupts are assumed to be disabled during | ||||
|                initialization.  */ | ||||
|             saved_thread_ptr =  _tx_thread_execute_ptr; | ||||
|  | ||||
|             /* Determine if there is thread ready for execution.  */ | ||||
|             if (saved_thread_ptr != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, a thread is ready for execution when initialization completes.  */ | ||||
|  | ||||
|                 /* Save the current preemption-threshold.  */ | ||||
|                 saved_threshold =  saved_thread_ptr -> tx_thread_preempt_threshold; | ||||
|  | ||||
|                 /* For initialization, temporarily set the preemption-threshold to the | ||||
|                    priority level to make sure the highest-priority thread runs once | ||||
|                    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; | ||||
|         } | ||||
|  | ||||
| #ifndef TX_INLINE_THREAD_RESUME_SUSPEND | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Resume the thread!  */ | ||||
|         _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #else | ||||
|  | ||||
|         /* Temporarily disable preemption.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Call the actual resume service to resume the thread.  */ | ||||
|         _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|         /* Determine if the thread's preemption-threshold needs to be restored.  */ | ||||
|         if (saved_thread_ptr != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* 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; | ||||
|         } | ||||
|  | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|  | ||||
|         /* Disable interrupts.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* Setup successful return status.  */ | ||||
|         status =  TX_SUCCESS; | ||||
| #else | ||||
|  | ||||
|         /* Return successful completion.  */ | ||||
|         return(TX_SUCCESS); | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #else | ||||
|  | ||||
|         /* In-line thread resumption processing follows, which is effectively just taking the | ||||
|            logic in tx_thread_system_resume.c and placing it here!  */ | ||||
|  | ||||
|         /* Resume the thread!  */ | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|         /* If trace is enabled, save the current event pointer.  */ | ||||
|         entry_ptr =  _tx_trace_buffer_current_ptr; | ||||
| #endif | ||||
|  | ||||
|         /* Log the thread status change.  */ | ||||
|         TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESUME, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&execute_ptr), TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), TX_TRACE_INTERNAL_EVENTS) | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|         /* Save the time stamp for later comparison to verify that | ||||
|            the event hasn't been overwritten by the time we have | ||||
|            computed the next thread to execute.  */ | ||||
|         if (entry_ptr != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Save time stamp.  */ | ||||
|             time_stamp =  entry_ptr -> tx_trace_buffer_entry_time_stamp; | ||||
|         } | ||||
| #endif | ||||
|  | ||||
|         /* Make this thread ready.  */ | ||||
|  | ||||
|         /* Change the state to ready.  */ | ||||
|         thread_ptr -> tx_thread_state =  TX_READY; | ||||
|  | ||||
|         /* Pickup priority of thread.  */ | ||||
|         priority =  thread_ptr -> tx_thread_priority; | ||||
|  | ||||
|         /* Thread state change.  */ | ||||
|         TX_THREAD_STATE_CHANGE(thread_ptr, TX_READY) | ||||
|  | ||||
|         /* Log the thread status change.  */ | ||||
|         TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_READY) | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|         /* Increment the total number of thread resumptions.  */ | ||||
|         _tx_thread_performance_resume_count++; | ||||
|  | ||||
|         /* Increment this thread's resume count.  */ | ||||
|         thread_ptr -> tx_thread_performance_resume_count++; | ||||
| #endif | ||||
|  | ||||
|         /* Determine if there are other threads at this priority that are | ||||
|            ready.  */ | ||||
|         head_ptr =  _tx_thread_priority_list[priority]; | ||||
|         if (head_ptr == TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* First thread at this priority ready.  Add to the front of the list.  */ | ||||
|             _tx_thread_priority_list[priority] =       thread_ptr; | ||||
|             thread_ptr -> tx_thread_ready_next =       thread_ptr; | ||||
|             thread_ptr -> tx_thread_ready_previous =   thread_ptr; | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|  | ||||
|             /* Calculate the index into the bit map array.  */ | ||||
|             map_index =  priority/((UINT) 32); | ||||
|  | ||||
|             /* Set the active bit to remember that the priority map has something set.  */ | ||||
|             TX_DIV32_BIT_SET(priority, priority_bit) | ||||
|             _tx_thread_priority_map_active =  _tx_thread_priority_map_active | priority_bit; | ||||
| #endif | ||||
|  | ||||
|             /* Or in the thread's priority bit.  */ | ||||
|             TX_MOD32_BIT_SET(priority, priority_bit) | ||||
|             _tx_thread_priority_maps[MAP_INDEX] =  _tx_thread_priority_maps[MAP_INDEX] | priority_bit; | ||||
|  | ||||
|             /* Determine if this newly ready thread is the highest priority.  */ | ||||
|             if (priority < _tx_thread_highest_priority) | ||||
|             { | ||||
|  | ||||
|                 /* A new highest priority thread is present. */ | ||||
|  | ||||
|                 /* Update the highest priority variable.  */ | ||||
|                 _tx_thread_highest_priority =  priority; | ||||
|  | ||||
|                 /* Pickup the execute pointer. Since it is going to be referenced multiple | ||||
|                    times, it is placed in a local variable.  */ | ||||
|                 execute_ptr =  _tx_thread_execute_ptr; | ||||
|  | ||||
|                 /* Determine if no thread is currently executing.  */ | ||||
|                 if (execute_ptr == TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     /* Simply setup the execute pointer.  */ | ||||
|                     _tx_thread_execute_ptr =  thread_ptr; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* Another thread has been scheduled for execution.  */ | ||||
|  | ||||
|                     /* Check to see if this is a higher priority thread and determine if preemption is allowed.  */ | ||||
|                     if (priority < execute_ptr -> tx_thread_preempt_threshold) | ||||
|                     { | ||||
|  | ||||
| #ifndef TX_DISABLE_PREEMPTION_THRESHOLD | ||||
|  | ||||
|                         /* Determine if the preempted thread had preemption-threshold set.  */ | ||||
|                         if (execute_ptr -> tx_thread_preempt_threshold != execute_ptr -> tx_thread_priority) | ||||
|                         { | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|  | ||||
|                             /* Calculate the index into the bit map array.  */ | ||||
|                             map_index =  (execute_ptr -> tx_thread_priority)/((UINT) 32); | ||||
|  | ||||
|                             /* Set the active bit to remember that the preempt map has something set.  */ | ||||
|                             TX_DIV32_BIT_SET(execute_ptr -> tx_thread_priority, priority_bit) | ||||
|                             _tx_thread_preempted_map_active =  _tx_thread_preempted_map_active | priority_bit; | ||||
| #endif | ||||
|  | ||||
|                             /* Remember that this thread was preempted by a thread above the thread's threshold.  */ | ||||
|                             TX_MOD32_BIT_SET(execute_ptr -> tx_thread_priority, priority_bit) | ||||
|                             _tx_thread_preempted_maps[MAP_INDEX] =  _tx_thread_preempted_maps[MAP_INDEX] | priority_bit; | ||||
|                         } | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                         /* Determine if the caller is an interrupt or from a thread.  */ | ||||
|                         if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0)) | ||||
|                         { | ||||
|  | ||||
|                             /* Caller is a thread, so this is a solicited preemption.  */ | ||||
|                             _tx_thread_performance_solicited_preemption_count++; | ||||
|  | ||||
|                             /* Increment the thread's solicited preemption counter.  */ | ||||
|                             execute_ptr -> tx_thread_performance_solicited_preemption_count++; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) | ||||
|                             { | ||||
|  | ||||
|                                 /* Caller is an interrupt, so this is an interrupt preemption.  */ | ||||
|                                 _tx_thread_performance_interrupt_preemption_count++; | ||||
|  | ||||
|                                 /* Increment the thread's interrupt preemption counter.  */ | ||||
|                                 execute_ptr -> tx_thread_performance_interrupt_preemption_count++; | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         /* Remember the thread that preempted this thread.  */ | ||||
|                         execute_ptr -> tx_thread_performance_last_preempting_thread =  thread_ptr; | ||||
| #endif | ||||
|  | ||||
|                         /* Yes, modify the execute thread pointer.  */ | ||||
|                         _tx_thread_execute_ptr =  thread_ptr; | ||||
|  | ||||
| #ifndef TX_MISRA_ENABLE | ||||
|  | ||||
|                         /* If MISRA is not-enabled, insert a preemption and return in-line for performance.  */ | ||||
|  | ||||
|                         /* Determine if the thread's preemption-threshold needs to be restored.  */ | ||||
|                         if (saved_thread_ptr != TX_NULL) | ||||
|                         { | ||||
|  | ||||
|                             /* 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; | ||||
|                         } | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                         /* Is the execute pointer different?  */ | ||||
|                         if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) | ||||
|                         { | ||||
|  | ||||
|                             /* Move to next entry.  */ | ||||
|                             _tx_thread_performance__execute_log_index++; | ||||
|  | ||||
|                             /* Check for wrap condition.  */ | ||||
|                             if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) | ||||
|                             { | ||||
|  | ||||
|                                 /* Set the index to the beginning.  */ | ||||
|                                 _tx_thread_performance__execute_log_index =  ((UINT) 0); | ||||
|                             } | ||||
|  | ||||
|                             /* Log the new execute pointer.  */ | ||||
|                             _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] =  _tx_thread_execute_ptr; | ||||
|                         } | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|                         /* Check that the event time stamp is unchanged.  A different | ||||
|                            timestamp means that a later event wrote over the thread | ||||
|                            resume event. In that case, do nothing here.  */ | ||||
|                         if (entry_ptr != TX_NULL) | ||||
|                         { | ||||
|  | ||||
|                             /* Is the timestamp the same?  */ | ||||
|                             if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) | ||||
|                             { | ||||
|  | ||||
|                                 /* Timestamp is the same, set the "next thread pointer" to NULL. This can | ||||
|                                    be used by the trace analysis tool to show idle system conditions.  */ | ||||
|                                 entry_ptr -> tx_trace_buffer_entry_information_field_4 =  TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); | ||||
|                             } | ||||
|                         } | ||||
| #endif | ||||
|  | ||||
|                         /* Restore interrupts.  */ | ||||
|                         TX_RESTORE | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|  | ||||
|                         /* Pickup the next execute pointer.  */ | ||||
|                         thread_ptr =  _tx_thread_execute_ptr; | ||||
|  | ||||
|                         /* Check this thread's stack.  */ | ||||
|                         TX_THREAD_STACK_CHECK(thread_ptr) | ||||
| #endif | ||||
|  | ||||
|                         /* Now determine if preemption should take place. This is only possible if the current thread pointer is | ||||
|                            not the same as the execute thread pointer AND the system state and preempt disable flags are clear.  */ | ||||
|                         TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) | ||||
|                         if (combined_flags == ((ULONG) 0)) | ||||
|                         { | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                             /* There is another thread ready to run and will be scheduled upon return.  */ | ||||
|                             _tx_thread_performance_non_idle_return_count++; | ||||
| #endif | ||||
|  | ||||
|                             /* Preemption is needed - return to the system!  */ | ||||
|                             _tx_thread_system_return(); | ||||
|                         } | ||||
|  | ||||
|                         /* Return in-line when MISRA is not enabled.  */ | ||||
|                         return(TX_SUCCESS); | ||||
| #endif | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* No, there are other threads at this priority already ready.  */ | ||||
|  | ||||
|             /* Just add this thread to the priority list.  */ | ||||
|             tail_ptr =                                 head_ptr -> tx_thread_ready_previous; | ||||
|             tail_ptr -> tx_thread_ready_next =         thread_ptr; | ||||
|             head_ptr -> tx_thread_ready_previous =     thread_ptr; | ||||
|             thread_ptr -> tx_thread_ready_previous =   tail_ptr; | ||||
|             thread_ptr -> tx_thread_ready_next =       head_ptr; | ||||
|         } | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|         /* Determine if we should log the execute pointer.  */ | ||||
|  | ||||
|         /* Is the execute pointer different?  */ | ||||
|         if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) | ||||
|         { | ||||
|  | ||||
|             /* Move to next entry.  */ | ||||
|             _tx_thread_performance__execute_log_index++; | ||||
|  | ||||
|             /* Check for wrap condition.  */ | ||||
|             if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) | ||||
|             { | ||||
|  | ||||
|                 /* Set the index to the beginning.  */ | ||||
|                 _tx_thread_performance__execute_log_index =  ((UINT) 0); | ||||
|             } | ||||
|  | ||||
|             /* Log the new execute pointer.  */ | ||||
|             _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] =  _tx_thread_execute_ptr; | ||||
|         } | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|         /* Check that the event time stamp is unchanged.  A different | ||||
|            timestamp means that a later event wrote over the thread | ||||
|            resume event. In that case, do nothing here.  */ | ||||
|         if (entry_ptr != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Is the timestamp the same?  */ | ||||
|             if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) | ||||
|             { | ||||
|  | ||||
|                 /* Timestamp is the same, set the "next thread pointer" to NULL. This can | ||||
|                    be used by the trace analysis tool to show idle system conditions.  */ | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|               entry_ptr -> tx_trace_buffer_entry_info_4 =  TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); | ||||
| #else | ||||
|               entry_ptr -> tx_trace_buffer_entry_information_field_4 =  TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); | ||||
| #endif | ||||
|             } | ||||
|         } | ||||
| #endif | ||||
|  | ||||
|         /* Determine if the thread's preemption-threshold needs to be restored.  */ | ||||
|         if (saved_thread_ptr != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* 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; | ||||
|         } | ||||
|  | ||||
|         /* Setup successful return status.  */ | ||||
|         status =  TX_SUCCESS; | ||||
| #endif | ||||
|     } | ||||
|     else if (thread_ptr -> tx_thread_delayed_suspend == TX_TRUE) | ||||
|     { | ||||
|  | ||||
|         /* Clear the delayed suspension.  */ | ||||
|         thread_ptr -> tx_thread_delayed_suspend =  TX_FALSE; | ||||
|  | ||||
|         /* Setup delayed suspend lifted return status.  */ | ||||
|         status =  TX_SUSPEND_LIFTED; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Setup invalid resume return status.  */ | ||||
|         status =  TX_RESUME_ERROR; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
| #ifdef TX_INLINE_THREAD_RESUME_SUSPEND | ||||
|  | ||||
|     /* Pickup thread pointer.  */ | ||||
|     TX_THREAD_GET_CURRENT(current_thread) | ||||
|  | ||||
|     /* Determine if a preemption condition is present.  */ | ||||
|     if (current_thread != _tx_thread_execute_ptr) | ||||
|     { | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|  | ||||
|         /* Pickup the next execute pointer.  */ | ||||
|         thread_ptr =  _tx_thread_execute_ptr; | ||||
|  | ||||
|         /* Check this thread's stack.  */ | ||||
|         TX_THREAD_STACK_CHECK(thread_ptr) | ||||
| #endif | ||||
|  | ||||
|         /* Now determine if preemption should take place. This is only possible if the current thread pointer is | ||||
|            not the same as the execute thread pointer AND the system state and preempt disable flags are clear.  */ | ||||
|         TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) | ||||
|         if (combined_flags == ((ULONG) 0)) | ||||
|         { | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|             /* There is another thread ready to run and will be scheduled upon return.  */ | ||||
|             _tx_thread_performance_non_idle_return_count++; | ||||
| #endif | ||||
|  | ||||
|             /* Preemption is needed - return to the system!  */ | ||||
|             _tx_thread_system_return(); | ||||
|         } | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     /* Return completion status. */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										203
									
								
								Middlewares/ST/threadx/common/src/tx_thread_shell_entry.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								Middlewares/ST/threadx/common/src/tx_thread_shell_entry.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_shell_entry                              PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function calls the specified entry function of the thread.  It */ | ||||
| /*    also provides a place for the thread's entry function to return.    */ | ||||
| /*    If the thread returns, this function places the thread in a         */ | ||||
| /*    "COMPLETED" state.                                                  */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_entry                      Thread's entry function           */ | ||||
| /*    _tx_thread_system_suspend         Thread suspension routine         */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Initial thread stack frame                                          */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_thread_shell_entry(VOID) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
| VOID            (*entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type); | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     /* Pickup thread pointer.  */ | ||||
|     TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
|     /* Perform any additional activities for tool or user purpose.  */ | ||||
|     TX_THREAD_STARTED_EXTENSION(thread_ptr) | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Pickup the entry/exit application callback routine.  */ | ||||
|     entry_exit_notify =  thread_ptr -> tx_thread_entry_exit_notify; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Determine if an application callback routine is specified.  */ | ||||
|     if (entry_exit_notify != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Yes, notify application that this thread has been entered!  */ | ||||
|         (entry_exit_notify)(thread_ptr, TX_THREAD_ENTRY); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     /* Call current thread's entry function.  */ | ||||
|     (thread_ptr -> tx_thread_entry) (thread_ptr -> tx_thread_entry_parameter); | ||||
|  | ||||
|     /* Suspend thread with a "completed" state.  */ | ||||
|  | ||||
|     /* Determine if the application is using mutexes.  */ | ||||
|     if (_tx_thread_mutex_release != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Yes, call the mutex release function via a function pointer that | ||||
|            is setup during mutex initialization.  */ | ||||
|         (_tx_thread_mutex_release)(thread_ptr); | ||||
|     } | ||||
|  | ||||
|     /* Lockout interrupts while the thread state is setup.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|     /* Pickup the entry/exit application callback routine again.  */ | ||||
|     entry_exit_notify =  thread_ptr -> tx_thread_entry_exit_notify; | ||||
| #endif | ||||
|  | ||||
|     /* Set the status to suspending, in order to indicate the suspension | ||||
|        is in progress.  */ | ||||
|     thread_ptr -> tx_thread_state =  TX_COMPLETED; | ||||
|  | ||||
|     /* Thread state change.  */ | ||||
|     TX_THREAD_STATE_CHANGE(thread_ptr, TX_COMPLETED) | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|     /* Determine if an application callback routine is specified.  */ | ||||
|     if (entry_exit_notify != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Yes, notify application that this thread has exited!  */ | ||||
|         (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     /* Perform any additional activities for tool or user purpose.  */ | ||||
|     TX_THREAD_COMPLETED_EXTENSION(thread_ptr) | ||||
|  | ||||
|     /* Call actual non-interruptable thread suspension routine.  */ | ||||
|     _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0)); | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
| #else | ||||
|  | ||||
|     /* Set the suspending flag. */ | ||||
|     thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|     /* Setup for no timeout period.  */ | ||||
|     thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  ((ULONG) 0); | ||||
|  | ||||
|     /* Temporarily disable preemption.  */ | ||||
|     _tx_thread_preempt_disable++; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Perform any additional activities for tool or user purpose.  */ | ||||
|     TX_THREAD_COMPLETED_EXTENSION(thread_ptr) | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|     /* Determine if an application callback routine is specified.  */ | ||||
|     if (entry_exit_notify != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Yes, notify application that this thread has exited!  */ | ||||
|         (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     /* Call actual thread suspension routine.  */ | ||||
|     _tx_thread_system_suspend(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #ifdef TX_SAFETY_CRITICAL | ||||
|  | ||||
|     /* If we ever get here, raise safety critical exception.  */ | ||||
|     TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0); | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										200
									
								
								Middlewares/ST/threadx/common/src/tx_thread_sleep.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								Middlewares/ST/threadx/common/src/tx_thread_sleep.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,200 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_sleep                                    PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function handles application thread sleep requests.  If the    */ | ||||
| /*    sleep request was called from a non-thread, an error is returned.   */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    timer_ticks                           Number of timer ticks to sleep*/ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Return completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_suspend         Actual thread suspension          */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_thread_sleep(ULONG timer_ticks) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| UINT            status; | ||||
| TX_THREAD       *thread_ptr; | ||||
|  | ||||
|  | ||||
|     /* Lockout interrupts while the thread is being resumed.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* 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) | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Illegal caller of this service.  */ | ||||
|         status =  TX_CALLER_ERROR; | ||||
|     } | ||||
|  | ||||
|     /* Is the caller an ISR or Initialization?  */ | ||||
|     else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Illegal caller of this service.  */ | ||||
|         status =  TX_CALLER_ERROR; | ||||
|     } | ||||
|  | ||||
| #ifndef TX_TIMER_PROCESS_IN_ISR | ||||
|  | ||||
|     /* Is the caller the system timer thread?  */ | ||||
|     else if (thread_ptr == &_tx_timer_thread) | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Illegal caller of this service.  */ | ||||
|         status =  TX_CALLER_ERROR; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     /* Determine if the requested number of ticks is zero.  */ | ||||
|     else if (timer_ticks == ((ULONG) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Just return with a successful status.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Determine if the preempt disable flag is non-zero.  */ | ||||
|         if (_tx_thread_preempt_disable != ((UINT) 0)) | ||||
|         { | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion.  */ | ||||
|             status =  TX_CALLER_ERROR; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|             TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SLEEP, TX_ULONG_TO_POINTER_CONVERT(timer_ticks), thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&status), 0, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|             /* Log this kernel call.  */ | ||||
|             TX_EL_THREAD_SLEEP_INSERT | ||||
|  | ||||
|             /* Suspend the current thread.  */ | ||||
|  | ||||
|             /* Set the state to suspended.  */ | ||||
|             thread_ptr -> tx_thread_state =    TX_SLEEP; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Call actual non-interruptable thread suspension routine.  */ | ||||
|             _tx_thread_system_ni_suspend(thread_ptr, timer_ticks); | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #else | ||||
|  | ||||
|             /* Set the suspending flag. */ | ||||
|             thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|             /* Initialize the status to successful.  */ | ||||
|             thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS; | ||||
|  | ||||
|             /* Setup the timeout period.  */ | ||||
|             thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  timer_ticks; | ||||
|  | ||||
|             /* Temporarily disable preemption.  */ | ||||
|             _tx_thread_preempt_disable++; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Call actual thread suspension routine.  */ | ||||
|             _tx_thread_system_suspend(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|             /* Return status to the caller.  */ | ||||
|             status =  thread_ptr -> tx_thread_suspend_status; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										183
									
								
								Middlewares/ST/threadx/common/src/tx_thread_stack_analyze.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								Middlewares/ST/threadx/common/src/tx_thread_stack_analyze.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,183 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_stack_analyze                            PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function analyzes the stack to calculate the highest stack     */ | ||||
| /*    pointer in the thread's stack. This can then be used to derive the  */ | ||||
| /*    minimum amount of stack left for any given thread.                  */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                            Thread control block pointer  */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    ThreadX internal code                                               */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_thread_stack_analyze(TX_THREAD *thread_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| ULONG       *stack_ptr; | ||||
| ULONG       *stack_lowest; | ||||
| ULONG       *stack_highest; | ||||
| ULONG       size; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Determine if the thread pointer is NULL.  */ | ||||
|     if (thread_ptr != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Determine if the thread ID is invalid.  */ | ||||
|         if (thread_ptr -> tx_thread_id == TX_THREAD_ID) | ||||
|         { | ||||
|  | ||||
|             /* Pickup the current stack variables.  */ | ||||
|             stack_lowest =   TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_start); | ||||
|  | ||||
|             /* Determine if the pointer is null.  */ | ||||
|             if (stack_lowest != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Pickup the highest stack pointer.  */ | ||||
|                 stack_highest =  TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_highest_ptr); | ||||
|  | ||||
|                 /* Determine if the pointer is null.  */ | ||||
|                 if (stack_highest != TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     /* Restore interrupts.  */ | ||||
|                     TX_RESTORE | ||||
|  | ||||
|                     /* We need to binary search the remaining stack for missing 0xEFEFEFEF 32-bit data pattern. | ||||
|                        This is a best effort algorithm to find the highest stack usage. */ | ||||
|                     do | ||||
|                     { | ||||
|  | ||||
|                         /* Calculate the size again. */ | ||||
|                         size =  (ULONG) (TX_ULONG_POINTER_DIF(stack_highest, stack_lowest))/((ULONG) 2); | ||||
|                         stack_ptr =  TX_ULONG_POINTER_ADD(stack_lowest, size); | ||||
|  | ||||
|                         /* Determine if the pattern is still there.  */ | ||||
|                         if (*stack_ptr != TX_STACK_FILL) | ||||
|                         { | ||||
|  | ||||
|                             /* Update the stack highest, since we need to look in the upper half now.  */ | ||||
|                             stack_highest =  stack_ptr; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* Update the stack lowest, since we need to look in the lower half now.  */ | ||||
|                             stack_lowest =  stack_ptr; | ||||
|                         } | ||||
|  | ||||
|                     } while(size > ((ULONG) 1)); | ||||
|  | ||||
|                     /* Position to first used word - at this point we are within a few words.  */ | ||||
|                     while (*stack_ptr == TX_STACK_FILL) | ||||
|                     { | ||||
|  | ||||
|                         /* Position to next word in stack.  */ | ||||
|                         stack_ptr =  TX_ULONG_POINTER_ADD(stack_ptr, 1); | ||||
|                     } | ||||
|  | ||||
|                     /* Optional processing extension.  */ | ||||
|                     TX_THREAD_STACK_ANALYZE_EXTENSION | ||||
|  | ||||
|                     /* Disable interrupts.  */ | ||||
|                     TX_DISABLE | ||||
|  | ||||
|                     /* Check to see if the thread is still created.  */ | ||||
|                     if (thread_ptr -> tx_thread_id == TX_THREAD_ID) | ||||
|                     { | ||||
|  | ||||
|                         /* Yes, thread is still created.  */ | ||||
|  | ||||
|                         /* Now check the new highest stack pointer is past the stack start.  */ | ||||
|                         if (stack_ptr > (TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_start))) | ||||
|                         { | ||||
|  | ||||
|                             /* Yes, now check that the new highest stack pointer is less than the previous highest stack pointer.  */ | ||||
|                             if (stack_ptr < (TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_highest_ptr))) | ||||
|                             { | ||||
|  | ||||
|                                 /* Yes, is the current highest stack pointer pointing at used memory?  */ | ||||
|                                 if (*stack_ptr != TX_STACK_FILL) | ||||
|                                 { | ||||
|  | ||||
|                                     /* Yes, setup the highest stack usage.  */ | ||||
|                                     thread_ptr -> tx_thread_stack_highest_ptr =  stack_ptr; | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,120 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #if defined(TX_MISRA_ENABLE) || defined(TX_ENABLE_STACK_CHECKING) || defined(TX_PORT_THREAD_STACK_ERROR_HANDLING) | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_stack_error_handler                      PORTABLE C      */ | ||||
| /*                                                           6.1.9        */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function processes stack errors detected during run-time. The  */ | ||||
| /*    processing currently consists of a spin loop.                       */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                            Thread control block pointer  */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    ThreadX internal code                                               */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            update misra support,       */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*  10-16-2020     William E. Lamie         Modified comment(s),          */ | ||||
| /*                                            fixed link issue,           */ | ||||
| /*                                            resulting in version 6.1.1  */ | ||||
| /*  06-02-2021     William E. Lamie         Modified comment(s),          */ | ||||
| /*                                            fixed link issue, added     */ | ||||
| /*                                            conditional compilation     */ | ||||
| /*                                            for ARMv8-M (Cortex M23/33) */ | ||||
| /*                                            resulting in version 6.1.7  */ | ||||
| /*  10-15-2021     Yuxin Zhou               Modified comment(s), improved */ | ||||
| /*                                            stack check error handling, */ | ||||
| /*                                            resulting in version 6.1.9  */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_thread_stack_error_handler(TX_THREAD *thread_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| #if defined(TX_ENABLE_STACK_CHECKING) || defined(TX_PORT_THREAD_STACK_ERROR_HANDLING) | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Determine if the application has registered an error handler.  */ | ||||
|     if (_tx_thread_application_stack_error_handler != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Yes, an error handler is present, simply call the application error handler.  */ | ||||
|         (_tx_thread_application_stack_error_handler)(thread_ptr); | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
| #else | ||||
|  | ||||
|     /* Access input argument just for the sake of lint, MISRA, etc.  */ | ||||
|     if (thread_ptr != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Disable interrupts.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
| #endif | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										134
									
								
								Middlewares/ST/threadx/common/src/tx_thread_stack_error_notify.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								Middlewares/ST/threadx/common/src/tx_thread_stack_error_notify.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #if defined(TX_ENABLE_STACK_CHECKING) || defined(TX_PORT_THREAD_STACK_ERROR_HANDLING) | ||||
| #include "tx_trace.h" | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_stack_error_notify                       PORTABLE C      */ | ||||
| /*                                                           6.1.9        */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function registers an application stack error handler. If      */ | ||||
| /*    ThreadX detects a stack error, this application handler is called.  */ | ||||
| /*                                                                        */ | ||||
| /*    Note: stack checking must be enabled for this routine to serve any  */ | ||||
| /*    purpose via the TX_ENABLE_STACK_CHECKING define.                    */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    stack_error_handler                   Pointer to stack error        */ | ||||
| /*                                            handler, TX_NULL to disable */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Service return status         */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*  06-02-2021     Yuxin Zhou               Modified comment(s), added    */ | ||||
| /*                                            conditional compilation     */ | ||||
| /*                                            for ARMv8-M (Cortex M23/33) */ | ||||
| /*                                            resulting in version 6.1.7  */ | ||||
| /*  10-15-2021     Yuxin Zhou               Modified comment(s), improved */ | ||||
| /*                                            stack check error handling, */ | ||||
| /*                                            resulting in version 6.1.9  */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_thread_stack_error_notify(VOID (*stack_error_handler)(TX_THREAD *thread_ptr)) | ||||
| { | ||||
|  | ||||
| #if !defined(TX_ENABLE_STACK_CHECKING) && !defined(TX_PORT_THREAD_STACK_ERROR_HANDLING) | ||||
|  | ||||
| UINT        status; | ||||
|  | ||||
|  | ||||
|     /* Access input argument just for the sake of lint, MISRA, etc.  */ | ||||
|     if (stack_error_handler != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Stack checking is not enabled, just return an error.  */ | ||||
|         status =  TX_FEATURE_NOT_ENABLED; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Stack checking is not enabled, just return an error.  */ | ||||
|         status =  TX_FEATURE_NOT_ENABLED; | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
|  | ||||
| #else | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Make entry in event log.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_STACK_ERROR_NOTIFY, 0, 0, 0, 0, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|     /* Make entry in event log.  */ | ||||
|     TX_EL_THREAD_STACK_ERROR_NOTIFY_INSERT | ||||
|  | ||||
|     /* Setup global thread stack error handler.  */ | ||||
|     _tx_thread_application_stack_error_handler =  stack_error_handler; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return success to caller.  */ | ||||
|     return(TX_SUCCESS); | ||||
| #endif | ||||
| } | ||||
							
								
								
									
										849
									
								
								Middlewares/ST/threadx/common/src/tx_thread_suspend.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										849
									
								
								Middlewares/ST/threadx/common/src/tx_thread_suspend.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,849 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #ifdef TX_INLINE_THREAD_RESUME_SUSPEND | ||||
| #ifndef TX_NO_TIMER | ||||
| #include "tx_timer.h" | ||||
| #endif | ||||
| #endif | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_suspend                                  PORTABLE C      */ | ||||
| /*                                                           6.1.1        */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function handles application suspend requests.  If the suspend */ | ||||
| /*    requires actual processing, this function calls the actual suspend  */ | ||||
| /*    thread routine.                                                     */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                            Pointer to thread to suspend  */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Return completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_suspend         Actual thread suspension          */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*  10-16-2020     Yuxin Zhou               Modified comment(s), and      */ | ||||
| /*                                            added type cast to address  */ | ||||
| /*                                            a MISRA compliance issue,   */ | ||||
| /*                                            resulting in version 6.1.1  */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_thread_suspend(TX_THREAD *thread_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD  *current_thread; | ||||
| UINT        status; | ||||
|  | ||||
|  | ||||
| #ifndef TX_INLINE_THREAD_RESUME_SUSPEND | ||||
|  | ||||
|     /* Lockout interrupts while the thread is being suspended.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Pickup thread pointer.  */ | ||||
|     TX_THREAD_GET_CURRENT(current_thread) | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SUSPEND_API, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&status), 0, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_THREAD_SUSPEND_INSERT | ||||
|  | ||||
|     /* Check the specified thread's current status.  */ | ||||
|     if (thread_ptr -> tx_thread_state == TX_READY) | ||||
|     { | ||||
|  | ||||
|         /* Initialize status to success.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|  | ||||
|         /* Determine if we are in a thread context.  */ | ||||
|         if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0)) | ||||
|         { | ||||
|  | ||||
|             /* Yes, we are in a thread context.  */ | ||||
|  | ||||
|             /* Determine if the current thread is also the suspending thread.  */ | ||||
|             if (current_thread == thread_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Now determine if the preempt disable flag is non-zero.  */ | ||||
|                 if (_tx_thread_preempt_disable != ((UINT) 0)) | ||||
|                 { | ||||
|  | ||||
|                     /* Current thread cannot suspend when the preempt disable flag is non-zero, | ||||
|                        return an error.  */ | ||||
|                     status =  TX_SUSPEND_ERROR; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Determine if the status is still successful.  */ | ||||
|         if (status == TX_SUCCESS) | ||||
|         { | ||||
|  | ||||
|             /* Set the state to suspended.  */ | ||||
|             thread_ptr -> tx_thread_state =    TX_SUSPENDED; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Call actual non-interruptable thread suspension routine.  */ | ||||
|             _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0)); | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #else | ||||
|  | ||||
|             /* Set the suspending flag. */ | ||||
|             thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|             /* Setup for no timeout period.  */ | ||||
|             thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  ((ULONG) 0); | ||||
|  | ||||
|             /* Temporarily disable preemption.  */ | ||||
|             _tx_thread_preempt_disable++; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Call actual thread suspension routine.  */ | ||||
|             _tx_thread_system_suspend(thread_ptr); | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|  | ||||
|             /* Disable interrupts.  */ | ||||
|             TX_DISABLE | ||||
|  | ||||
|             /* Return success.  */ | ||||
|             status =  TX_SUCCESS; | ||||
| #else | ||||
|  | ||||
|             /* If MISRA is not enabled, return directly.  */ | ||||
|             return(TX_SUCCESS); | ||||
| #endif | ||||
|         } | ||||
|     } | ||||
|     else if (thread_ptr -> tx_thread_state == TX_TERMINATED) | ||||
|     { | ||||
|  | ||||
|         /* Thread is terminated.  */ | ||||
|         status =  TX_SUSPEND_ERROR; | ||||
|     } | ||||
|     else if (thread_ptr -> tx_thread_state == TX_COMPLETED) | ||||
|     { | ||||
|  | ||||
|         /* Thread is completed.  */ | ||||
|         status =  TX_SUSPEND_ERROR; | ||||
|     } | ||||
|     else if (thread_ptr -> tx_thread_state == TX_SUSPENDED) | ||||
|     { | ||||
|  | ||||
|         /* Already suspended, just set status to success.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Just set the delayed suspension flag.  */ | ||||
|         thread_ptr -> tx_thread_delayed_suspend =  TX_TRUE; | ||||
|  | ||||
|         /* Set status to success.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Always return success, since this function does not perform error | ||||
|        checking.  */ | ||||
|     return(status); | ||||
|  | ||||
| #else | ||||
|  | ||||
|     /* In-line thread suspension processing follows, which is effectively just taking the | ||||
|        logic in tx_thread_system_suspend.c and placing it here!  */ | ||||
|  | ||||
| UINT            priority; | ||||
| UINT            base_priority; | ||||
| ULONG           priority_map; | ||||
| ULONG           priority_bit; | ||||
| ULONG           combined_flags; | ||||
| TX_THREAD       *ready_next; | ||||
| TX_THREAD       *ready_previous; | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
| UINT            map_index; | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
| TX_TRACE_BUFFER_ENTRY       *entry_ptr; | ||||
| ULONG                       time_stamp =  ((ULONG) 0); | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     /* Pickup thread pointer.  */ | ||||
|     TX_THREAD_GET_CURRENT(current_thread) | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|  | ||||
|     /* Check this thread's stack.  */ | ||||
|     TX_THREAD_STACK_CHECK(thread_ptr) | ||||
| #endif | ||||
|  | ||||
|     /* Lockout interrupts while the thread is being suspended.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifndef TX_NO_TIMER | ||||
|  | ||||
|     /* Determine if this is the current thread.  */ | ||||
|     if (thread_ptr == current_thread) | ||||
|     { | ||||
|  | ||||
|         /* Yes, current thread is suspending - reset time slice for current thread.  */ | ||||
|         _tx_timer_time_slice =  thread_ptr -> tx_thread_new_time_slice; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SUSPEND_API, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&status), 0, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_THREAD_SUSPEND_INSERT | ||||
|  | ||||
|     /* Check the specified thread's current status.  */ | ||||
|     if (thread_ptr -> tx_thread_state == TX_READY) | ||||
|     { | ||||
|  | ||||
|         /* Initialize status to success.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|  | ||||
|         /* Determine if we are in a thread context.  */ | ||||
|         if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0)) | ||||
|         { | ||||
|  | ||||
|             /* Yes, we are in a thread context.  */ | ||||
|  | ||||
|             /* Determine if the current thread is also the suspending thread.  */ | ||||
|             if (current_thread == thread_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Now determine if the preempt disable flag is non-zero.  */ | ||||
|                 if (_tx_thread_preempt_disable != ((UINT) 0)) | ||||
|                 { | ||||
|  | ||||
|                     /* Current thread cannot suspend when the preempt disable flag is non-zero, | ||||
|                        return an error.  */ | ||||
|                     status =  TX_SUSPEND_ERROR; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Determine if the status is still successful.  */ | ||||
|         if (status == TX_SUCCESS) | ||||
|         { | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|             /* Increment the thread's suspend count.  */ | ||||
|             thread_ptr -> tx_thread_performance_suspend_count++; | ||||
|  | ||||
|             /* Increment the total number of thread suspensions.  */ | ||||
|             _tx_thread_performance_suspend_count++; | ||||
| #endif | ||||
|  | ||||
|             /* Set the state to suspended.  */ | ||||
|             thread_ptr -> tx_thread_state =    TX_SUSPENDED; | ||||
|  | ||||
|             /* Thread state change.  */ | ||||
|             TX_THREAD_STATE_CHANGE(thread_ptr, TX_SUSPENDED) | ||||
|  | ||||
|             /* Log the thread status change.  */ | ||||
|             TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, thread_ptr -> tx_thread_state) | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|             /* If trace is enabled, save the current event pointer.  */ | ||||
|             entry_ptr =  _tx_trace_buffer_current_ptr; | ||||
| #endif | ||||
|  | ||||
|             /* Log the thread status change.  */ | ||||
|             TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SUSPEND, thread_ptr, ((ULONG) thread_ptr -> tx_thread_state), TX_POINTER_TO_ULONG_CONVERT(&priority), TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), TX_TRACE_INTERNAL_EVENTS) | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|             /* Save the time stamp for later comparison to verify that | ||||
|                the event hasn't been overwritten by the time we have | ||||
|                computed the next thread to execute.  */ | ||||
|             if (entry_ptr != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Save time stamp.  */ | ||||
|                 time_stamp =  entry_ptr -> tx_trace_buffer_entry_time_stamp; | ||||
|             } | ||||
| #endif | ||||
|  | ||||
|             /* Pickup priority of thread.  */ | ||||
|             priority =  thread_ptr -> tx_thread_priority; | ||||
|  | ||||
|             /* Pickup the previous and next ready thread pointers.  */ | ||||
|             ready_next =      thread_ptr -> tx_thread_ready_next; | ||||
|             ready_previous =  thread_ptr -> tx_thread_ready_previous; | ||||
|  | ||||
|             /* Determine if there are other threads at this priority that are | ||||
|                ready.  */ | ||||
|             if (ready_next != thread_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, there are other threads at this priority ready.  */ | ||||
|  | ||||
|                 /* Just remove this thread from the priority list.  */ | ||||
|                 ready_next -> tx_thread_ready_previous =    ready_previous; | ||||
|                 ready_previous -> tx_thread_ready_next =    ready_next; | ||||
|  | ||||
|                 /* Determine if this is the head of the priority list.  */ | ||||
|                 if (_tx_thread_priority_list[priority] == thread_ptr) | ||||
|                 { | ||||
|  | ||||
|                     /* Update the head pointer of this priority list.  */ | ||||
|                     _tx_thread_priority_list[priority] =  ready_next; | ||||
|  | ||||
| #ifndef TX_DISABLE_PREEMPTION_THRESHOLD | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|  | ||||
|                     /* Calculate the index into the bit map array.  */ | ||||
|                     map_index =  priority/((UINT) 32); | ||||
| #endif | ||||
|  | ||||
|                     /* Check for a thread preempted that had preemption threshold set.  */ | ||||
|                     if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0)) | ||||
|                     { | ||||
|  | ||||
|                         /* Ensure that this thread's priority is clear in the preempt map.  */ | ||||
|                         TX_MOD32_BIT_SET(priority, priority_bit) | ||||
|                         _tx_thread_preempted_maps[MAP_INDEX] =  _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit)); | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|  | ||||
|                         /* Determine if there are any other bits set in this preempt map.  */ | ||||
|                         if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0)) | ||||
|                         { | ||||
|  | ||||
|                             /* No, clear the active bit to signify this preempt map has nothing set.  */ | ||||
|                             TX_DIV32_BIT_SET(priority, priority_bit) | ||||
|                             _tx_thread_preempted_map_active =  _tx_thread_preempted_map_active & (~(priority_bit)); | ||||
|                         } | ||||
| #endif | ||||
|                     } | ||||
| #endif | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* This is the only thread at this priority ready to run.  Set the head | ||||
|                    pointer to NULL.  */ | ||||
|                 _tx_thread_priority_list[priority] =    TX_NULL; | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|  | ||||
|                 /* Calculate the index into the bit map array.  */ | ||||
|                 map_index =  priority/((UINT) 32); | ||||
| #endif | ||||
|  | ||||
|                 /* Clear this priority bit in the ready priority bit map.  */ | ||||
|                 TX_MOD32_BIT_SET(priority, priority_bit) | ||||
|                 _tx_thread_priority_maps[MAP_INDEX] =  _tx_thread_priority_maps[MAP_INDEX] & (~(priority_bit)); | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|  | ||||
|                 /* Determine if there are any other bits set in this priority map.  */ | ||||
|                 if (_tx_thread_priority_maps[MAP_INDEX] == ((ULONG) 0)) | ||||
|                 { | ||||
|  | ||||
|                     /* No, clear the active bit to signify this priority map has nothing set.  */ | ||||
|                     TX_DIV32_BIT_SET(priority, priority_bit) | ||||
|                     _tx_thread_priority_map_active =  _tx_thread_priority_map_active & (~(priority_bit)); | ||||
|                 } | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_DISABLE_PREEMPTION_THRESHOLD | ||||
|  | ||||
|                 /* Check for a thread preempted that had preemption-threshold set.  */ | ||||
|                 if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0)) | ||||
|                 { | ||||
|  | ||||
|                     /* Ensure that this thread's priority is clear in the preempt map.  */ | ||||
|                     TX_MOD32_BIT_SET(priority, priority_bit) | ||||
|                     _tx_thread_preempted_maps[MAP_INDEX] =  _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit)); | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|  | ||||
|                     /* Determine if there are any other bits set in this preempt map.  */ | ||||
|                     if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0)) | ||||
|                     { | ||||
|  | ||||
|                         /* No, clear the active bit to signify this preempted map has nothing set.  */ | ||||
|                         TX_DIV32_BIT_SET(priority, priority_bit) | ||||
|                         _tx_thread_preempted_map_active =  _tx_thread_preempted_map_active & (~(priority_bit)); | ||||
|                     } | ||||
| #endif | ||||
|                 } | ||||
| #endif | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|  | ||||
|                 /* Calculate the index to find the next highest priority thread ready for execution.  */ | ||||
|                 priority_map =    _tx_thread_priority_map_active; | ||||
|  | ||||
|                 /* Determine if there is anything.   */ | ||||
|                 if (priority_map != ((ULONG) 0)) | ||||
|                 { | ||||
|  | ||||
|                     /* Calculate the lowest bit set in the priority map. */ | ||||
|                     TX_LOWEST_SET_BIT_CALCULATE(priority_map, map_index) | ||||
|                 } | ||||
|  | ||||
|                 /* Calculate the base priority as well.  */ | ||||
|                 base_priority =  map_index * ((UINT) 32); | ||||
| #else | ||||
|  | ||||
|                 /* Setup the base priority to zero.  */ | ||||
|                 base_priority =   ((UINT) 0); | ||||
| #endif | ||||
|  | ||||
|                 /* Setup working variable for the priority map.  */ | ||||
|                 priority_map =    _tx_thread_priority_maps[MAP_INDEX]; | ||||
|  | ||||
|                 /* Make a quick check for no other threads ready for execution.  */ | ||||
|                 if (priority_map == ((ULONG) 0)) | ||||
|                 { | ||||
|  | ||||
|                     /* Nothing else is ready.  Set highest priority and execute thread | ||||
|                        accordingly.  */ | ||||
|                     _tx_thread_highest_priority =  ((UINT) TX_MAX_PRIORITIES); | ||||
|                     _tx_thread_execute_ptr =       TX_NULL; | ||||
|  | ||||
| #ifndef TX_MISRA_ENABLE | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|                     /* Check that the event time stamp is unchanged.  A different | ||||
|                        timestamp means that a later event wrote over the thread | ||||
|                        suspend event. In that case, do nothing here.  */ | ||||
|                     if (entry_ptr != TX_NULL) | ||||
|                     { | ||||
|  | ||||
|                         /* Is the timestamp the same?  */ | ||||
|                         if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) | ||||
|                         { | ||||
|  | ||||
|                             /* Timestamp is the same, set the "next thread pointer" to the new value of the | ||||
|                                next thread to execute. This can be used by the trace analysis tool to keep | ||||
|                                track of next thread execution.  */ | ||||
|                             entry_ptr -> tx_trace_buffer_entry_information_field_4 =  0; | ||||
|                         } | ||||
|                     } | ||||
| #endif | ||||
|  | ||||
|                     /* Restore interrupts.  */ | ||||
|                     TX_RESTORE | ||||
|  | ||||
|                     /* Determine if preemption should take place. This is only possible if the current thread pointer is | ||||
|                        not the same as the execute thread pointer AND the system state and preempt disable flags are clear.  */ | ||||
|                     TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) | ||||
|                     if (combined_flags == ((ULONG) 0)) | ||||
|                     { | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                         /* Yes, increment the return to idle return count.  */ | ||||
|                         _tx_thread_performance_idle_return_count++; | ||||
| #endif | ||||
|  | ||||
|                         /* Preemption is needed - return to the system!  */ | ||||
|                         _tx_thread_system_return(); | ||||
|                     } | ||||
|  | ||||
|                     /* Return to caller.  */ | ||||
|                     return(TX_SUCCESS); | ||||
| #endif | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* Calculate the lowest bit set in the priority map. */ | ||||
|                     TX_LOWEST_SET_BIT_CALCULATE(priority_map, priority_bit) | ||||
|  | ||||
|                     /* Setup the next highest priority variable.  */ | ||||
|                     _tx_thread_highest_priority =  base_priority + priority_bit; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             /* Determine if this thread is the thread designated to execute.  */ | ||||
|             if (thread_ptr == _tx_thread_execute_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Pickup the highest priority thread to execute.  */ | ||||
|                 _tx_thread_execute_ptr =  _tx_thread_priority_list[_tx_thread_highest_priority]; | ||||
|  | ||||
| #ifndef TX_DISABLE_PREEMPTION_THRESHOLD | ||||
|  | ||||
|                 /* Determine if a previous thread with preemption-threshold was preempted.  */ | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|                 if (_tx_thread_preempted_map_active != ((ULONG) 0)) | ||||
| #else | ||||
|                 if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0)) | ||||
| #endif | ||||
|                 { | ||||
|  | ||||
|                     /* Yes, there was a thread preempted when it was using preemption-threshold.  */ | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                     /* Disable preemption.  */ | ||||
|                     _tx_thread_preempt_disable++; | ||||
|  | ||||
|                     /* Restore interrupts.  */ | ||||
|                     TX_RESTORE | ||||
|  | ||||
|                     /* Interrupts are enabled briefly here to keep the interrupt | ||||
|                        lockout time deterministic.  */ | ||||
|  | ||||
|                     /* Disable interrupts again.  */ | ||||
|                     TX_DISABLE | ||||
|  | ||||
|                     /* Decrement the preemption disable variable.  */ | ||||
|                     _tx_thread_preempt_disable--; | ||||
| #endif | ||||
|  | ||||
|                     /* Calculate the thread with preemption threshold set that | ||||
|                        was interrupted by a thread above the preemption level.  */ | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|  | ||||
|                     /* Calculate the index to find the next highest priority thread ready for execution.  */ | ||||
|                     priority_map =    _tx_thread_preempted_map_active; | ||||
|  | ||||
|                     /* Calculate the lowest bit set in the priority map. */ | ||||
|                     TX_LOWEST_SET_BIT_CALCULATE(priority_map, map_index) | ||||
|  | ||||
|                     /* Calculate the base priority as well.  */ | ||||
|                     base_priority =  map_index * ((UINT) 32); | ||||
| #else | ||||
|  | ||||
|                     /* Setup the base priority to zero.  */ | ||||
|                     base_priority =   ((UINT) 0); | ||||
| #endif | ||||
|  | ||||
|                     /* Setup temporary preempted map.  */ | ||||
|                     priority_map =  _tx_thread_preempted_maps[MAP_INDEX]; | ||||
|  | ||||
|                     /* Calculate the lowest bit set in the priority map. */ | ||||
|                     TX_LOWEST_SET_BIT_CALCULATE(priority_map, priority_bit) | ||||
|  | ||||
|                     /* Setup the highest priority preempted thread.  */ | ||||
|                     priority =  base_priority + priority_bit; | ||||
|  | ||||
|                     /* Determine if the next highest priority thread is above the highest priority threshold value.  */ | ||||
|                     if (_tx_thread_highest_priority >= (_tx_thread_priority_list[priority] -> tx_thread_preempt_threshold)) | ||||
|                     { | ||||
|  | ||||
|                         /* Thread not allowed to execute until earlier preempted thread finishes or lowers its | ||||
|                            preemption-threshold.  */ | ||||
|                         _tx_thread_execute_ptr =  _tx_thread_priority_list[priority]; | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|                         /* Check that the event time stamp is unchanged.  A different | ||||
|                            timestamp means that a later event wrote over the thread | ||||
|                            suspend event. In that case, do nothing here.  */ | ||||
|                         if (entry_ptr != TX_NULL) | ||||
|                         { | ||||
|  | ||||
|                             /* Is the timestamp the same?  */ | ||||
|                             if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) | ||||
|                             { | ||||
|  | ||||
|                                 /* Timestamp is the same, set the "next thread pointer" to the new value of the | ||||
|                                    next thread to execute. This can be used by the trace analysis tool to keep | ||||
|                                    track of next thread execution.  */ | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|                                 entry_ptr -> tx_trace_buffer_entry_info_4 =  TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); | ||||
| #else | ||||
|                                 entry_ptr -> tx_trace_buffer_entry_information_field_4 =  TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); | ||||
| #endif | ||||
|                             } | ||||
|                         } | ||||
| #endif | ||||
|  | ||||
|                         /* Clear the corresponding bit in the preempted map, since the preemption has been restored.  */ | ||||
|                         TX_MOD32_BIT_SET(priority, priority_bit) | ||||
|                         _tx_thread_preempted_maps[MAP_INDEX] =  _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit)); | ||||
|  | ||||
| #if TX_MAX_PRIORITIES > 32 | ||||
|  | ||||
|                         /* Determine if there are any other bits set in this preempt map.  */ | ||||
|                         if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0)) | ||||
|                         { | ||||
|  | ||||
|                             /* No, clear the active bit to signify this preempt map has nothing set.  */ | ||||
|                             TX_DIV32_BIT_SET(priority, priority_bit) | ||||
|                             _tx_thread_preempted_map_active =  _tx_thread_preempted_map_active & (~(priority_bit)); | ||||
|                         } | ||||
| #endif | ||||
|                     } | ||||
|                 } | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_MISRA_ENABLE | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                 /* Is the execute pointer different?  */ | ||||
|                 if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) | ||||
|                 { | ||||
|  | ||||
|                     /* Move to next entry.  */ | ||||
|                     _tx_thread_performance__execute_log_index++; | ||||
|  | ||||
|                     /* Check for wrap condition.  */ | ||||
|                     if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) | ||||
|                     { | ||||
|  | ||||
|                         /* Set the index to the beginning.  */ | ||||
|                         _tx_thread_performance__execute_log_index =  ((UINT) 0); | ||||
|                     } | ||||
|  | ||||
|                     /* Log the new execute pointer.  */ | ||||
|                     _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] =  _tx_thread_execute_ptr; | ||||
|                 } | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|                 /* Check that the event time stamp is unchanged.  A different | ||||
|                    timestamp means that a later event wrote over the thread | ||||
|                    suspend event. In that case, do nothing here.  */ | ||||
|                 if (entry_ptr != TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     /* Is the timestamp the same?  */ | ||||
|                     if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) | ||||
|                     { | ||||
|  | ||||
|                         /* Timestamp is the same, set the "next thread pointer" to the new value of the | ||||
|                            next thread to execute. This can be used by the trace analysis tool to keep | ||||
|                            track of next thread execution.  */ | ||||
|                         entry_ptr -> tx_trace_buffer_entry_information_field_4 =  0; | ||||
|                     } | ||||
|                 } | ||||
| #endif | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Determine if preemption should take place. This is only possible if the current thread pointer is | ||||
|                    not the same as the execute thread pointer AND the system state and preempt disable flags are clear.  */ | ||||
|                 TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) | ||||
|                 if (combined_flags == ((ULONG) 0)) | ||||
|                 { | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                     /* No, there is another thread ready to run and will be scheduled upon return.  */ | ||||
|                     _tx_thread_performance_non_idle_return_count++; | ||||
| #endif | ||||
|  | ||||
|                     /* Preemption is needed - return to the system!  */ | ||||
|                     _tx_thread_system_return(); | ||||
|                 } | ||||
|  | ||||
|                 /* Return to caller.  */ | ||||
|                 return(TX_SUCCESS); | ||||
| #endif | ||||
|             } | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|             /* Is the execute pointer different?  */ | ||||
|             if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Move to next entry.  */ | ||||
|                 _tx_thread_performance__execute_log_index++; | ||||
|  | ||||
|                 /* Check for wrap condition.  */ | ||||
|                 if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) | ||||
|                 { | ||||
|  | ||||
|                     /* Set the index to the beginning.  */ | ||||
|                     _tx_thread_performance__execute_log_index =  ((UINT) 0); | ||||
|                 } | ||||
|  | ||||
|                 /* Log the new execute pointer.  */ | ||||
|                 _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] =  _tx_thread_execute_ptr; | ||||
|             } | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|             /* Check that the event time stamp is unchanged.  A different | ||||
|                timestamp means that a later event wrote over the thread | ||||
|                suspend event. In that case, do nothing here.  */ | ||||
|             if (entry_ptr != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Is the timestamp the same?  */ | ||||
|                 if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) | ||||
|                 { | ||||
|  | ||||
|                     /* Timestamp is the same, set the "next thread pointer" to the new value of the | ||||
|                        next thread to execute. This can be used by the trace analysis tool to keep | ||||
|                        track of next thread execution.  */ | ||||
| #ifdef TX_MISRA_ENABLE | ||||
|                     entry_ptr -> tx_trace_buffer_entry_info_4 =  TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); | ||||
| #else | ||||
|                     entry_ptr -> tx_trace_buffer_entry_information_field_4 =  TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); | ||||
| #endif | ||||
|                 } | ||||
|             } | ||||
| #endif | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Determine if a preemption condition is present.  */ | ||||
|             if (current_thread != _tx_thread_execute_ptr) | ||||
|             { | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|  | ||||
|                 /* Pickup the next execute pointer.  */ | ||||
|                 thread_ptr =  _tx_thread_execute_ptr; | ||||
|  | ||||
|                 /* Check this thread's stack.  */ | ||||
|                 TX_THREAD_STACK_CHECK(thread_ptr) | ||||
| #endif | ||||
|  | ||||
|                 /* Determine if preemption should take place. This is only possible if the current thread pointer is | ||||
|                    not the same as the execute thread pointer AND the system state and preempt disable flags are clear.  */ | ||||
|                 TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) | ||||
|                 if (combined_flags == ((ULONG) 0)) | ||||
|                 { | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                     /* Determine if an idle system return is present.  */ | ||||
|                     if (_tx_thread_execute_ptr == TX_NULL) | ||||
|                     { | ||||
|  | ||||
|                         /* Yes, increment the return to idle return count.  */ | ||||
|                         _tx_thread_performance_idle_return_count++; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|  | ||||
|                         /* No, there is another thread ready to run and will be scheduled upon return.  */ | ||||
|                         _tx_thread_performance_non_idle_return_count++; | ||||
|                     } | ||||
| #endif | ||||
|  | ||||
|                     /* Preemption is needed - return to the system!  */ | ||||
|                     _tx_thread_system_return(); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             /* Disable interrupts.  */ | ||||
|             TX_DISABLE | ||||
|  | ||||
|             /* Return success.  */ | ||||
|             status =  TX_SUCCESS; | ||||
|         } | ||||
|     } | ||||
|     else if (thread_ptr -> tx_thread_state == TX_TERMINATED) | ||||
|     { | ||||
|  | ||||
|         /* Thread is terminated.  */ | ||||
|         status =  TX_SUSPEND_ERROR; | ||||
|     } | ||||
|     else if (thread_ptr -> tx_thread_state == TX_COMPLETED) | ||||
|     { | ||||
|  | ||||
|         /* Thread is completed.  */ | ||||
|         status =  TX_SUSPEND_ERROR; | ||||
|     } | ||||
|     else if (thread_ptr -> tx_thread_state == TX_SUSPENDED) | ||||
|     { | ||||
|  | ||||
|         /* Already suspended, just set status to success.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Just set the delayed suspension flag.  */ | ||||
|         thread_ptr -> tx_thread_delayed_suspend =  TX_TRUE; | ||||
|  | ||||
|         /* Set status to success.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,129 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_preempt_check                     PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function checks for preemption that could have occurred as a   */ | ||||
| /*    result scheduling activities occurring while the preempt disable    */ | ||||
| /*    flag was set.                                                       */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_return              Return to the system          */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Other ThreadX Components                                            */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_thread_system_preempt_check(VOID) | ||||
| { | ||||
|  | ||||
| ULONG           combined_flags; | ||||
| TX_THREAD       *current_thread; | ||||
| TX_THREAD       *thread_ptr; | ||||
|  | ||||
|  | ||||
|     /* Combine the system state and preempt disable flags into one for comparison.  */ | ||||
|     TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) | ||||
|  | ||||
|     /* Determine if we are in a system state (ISR or Initialization) or internal preemption is disabled.  */ | ||||
|     if (combined_flags == ((ULONG) 0)) | ||||
|     { | ||||
|  | ||||
|         /* No, at thread execution level so continue checking for preemption.  */ | ||||
|  | ||||
|         /* Pickup thread pointer.  */ | ||||
|         TX_THREAD_GET_CURRENT(current_thread) | ||||
|  | ||||
|         /* Pickup the next execute pointer.  */ | ||||
|         thread_ptr =  _tx_thread_execute_ptr; | ||||
|  | ||||
|         /* Determine if preemption should take place.  */ | ||||
|         if (current_thread != thread_ptr) | ||||
|         { | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|  | ||||
|             /* Check this thread's stack.  */ | ||||
|             TX_THREAD_STACK_CHECK(thread_ptr) | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|             /* Determine if an idle system return is present.  */ | ||||
|             if (thread_ptr == TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, increment the return to idle return count.  */ | ||||
|                 _tx_thread_performance_idle_return_count++; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* No, there is another thread ready to run and will be scheduled upon return.  */ | ||||
|                 _tx_thread_performance_non_idle_return_count++; | ||||
|             } | ||||
| #endif | ||||
|  | ||||
|             /* Return to the system so the higher priority thread can be scheduled.  */ | ||||
|             _tx_thread_system_return(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										1004
									
								
								Middlewares/ST/threadx/common/src/tx_thread_system_resume.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1004
									
								
								Middlewares/ST/threadx/common/src/tx_thread_system_resume.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1220
									
								
								Middlewares/ST/threadx/common/src/tx_thread_system_suspend.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1220
									
								
								Middlewares/ST/threadx/common/src/tx_thread_system_suspend.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										312
									
								
								Middlewares/ST/threadx/common/src/tx_thread_terminate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								Middlewares/ST/threadx/common/src/tx_thread_terminate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,312 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_terminate                                PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function handles application thread terminate requests.  Once  */ | ||||
| /*    a thread is terminated, it cannot be executed again unless it is    */ | ||||
| /*    deleted and recreated.                                              */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                            Pointer to thread to suspend  */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Return completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_system_deactivate           Timer deactivate function     */ | ||||
| /*    _tx_thread_system_suspend             Actual thread suspension      */ | ||||
| /*    _tx_thread_system_ni_suspend          Non-interruptable suspend     */ | ||||
| /*                                            thread                      */ | ||||
| /*    _tx_thread_system_preempt_check       Check for preemption          */ | ||||
| /*    Suspend Cleanup Routine               Suspension cleanup function   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_thread_terminate(TX_THREAD *thread_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| VOID        (*suspend_cleanup)(struct TX_THREAD_STRUCT *suspend_thread_ptr, ULONG suspension_sequence); | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
| VOID        (*entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id); | ||||
| #endif | ||||
| UINT        status; | ||||
| ULONG       suspension_sequence; | ||||
|  | ||||
|  | ||||
|     /* Default to successful completion.  */ | ||||
|     status =  TX_SUCCESS; | ||||
|  | ||||
|     /* Lockout interrupts while the thread is being terminated.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Deactivate thread timer, if active.  */ | ||||
|     _tx_timer_system_deactivate(&thread_ptr -> tx_thread_timer); | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_TERMINATE, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&suspend_cleanup), 0, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_THREAD_TERMINATE_INSERT | ||||
|  | ||||
|     /* Is the thread already terminated?  */ | ||||
|     if (thread_ptr -> tx_thread_state == TX_TERMINATED) | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Return success since thread is already terminated.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|     } | ||||
|  | ||||
|     /* Check the specified thread's current status.  */ | ||||
|     else if (thread_ptr -> tx_thread_state != TX_COMPLETED) | ||||
|     { | ||||
|  | ||||
|         /* Disable preemption.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|         /* Pickup the entry/exit application callback routine.  */ | ||||
|         entry_exit_notify =  thread_ptr -> tx_thread_entry_exit_notify; | ||||
| #endif | ||||
|  | ||||
|         /* Check to see if the thread is currently ready.  */ | ||||
|         if (thread_ptr -> tx_thread_state == TX_READY) | ||||
|         { | ||||
|  | ||||
|             /* Set the state to terminated.  */ | ||||
|             thread_ptr -> tx_thread_state =  TX_TERMINATED; | ||||
|  | ||||
|             /* Thread state change.  */ | ||||
|             TX_THREAD_STATE_CHANGE(thread_ptr, TX_TERMINATED) | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Determine if an application callback routine is specified.  */ | ||||
|             if (entry_exit_notify != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, notify application that this thread has exited!  */ | ||||
|                 (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT); | ||||
|             } | ||||
| #endif | ||||
|  | ||||
|             /* Call actual non-interruptable thread suspension routine.  */ | ||||
|             _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0)); | ||||
| #else | ||||
|  | ||||
|             /* Set the suspending flag.  */ | ||||
|             thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|             /* Setup for no timeout period.  */ | ||||
|             thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  ((ULONG) 0); | ||||
|  | ||||
|             /* Disable preemption.  */ | ||||
|             _tx_thread_preempt_disable++; | ||||
|  | ||||
|             /* Since the thread is currently ready, we don't need to | ||||
|                worry about calling the suspend cleanup routine!  */ | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Perform any additional activities for tool or user purpose.  */ | ||||
|             TX_THREAD_TERMINATED_EXTENSION(thread_ptr) | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Determine if an application callback routine is specified.  */ | ||||
|             if (entry_exit_notify != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, notify application that this thread has exited!  */ | ||||
|                 (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT); | ||||
|             } | ||||
| #endif | ||||
|  | ||||
|             /* Call actual thread suspension routine.  */ | ||||
|             _tx_thread_system_suspend(thread_ptr); | ||||
|  | ||||
|             /* Disable interrupts.  */ | ||||
|             TX_DISABLE | ||||
| #endif | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Change the state to terminated.  */ | ||||
|             thread_ptr -> tx_thread_state =    TX_TERMINATED; | ||||
|  | ||||
|             /* Thread state change.  */ | ||||
|             TX_THREAD_STATE_CHANGE(thread_ptr, TX_TERMINATED) | ||||
|  | ||||
|             /* Set the suspending flag.  This prevents the thread from being | ||||
|                resumed before the cleanup routine is executed.  */ | ||||
|             thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|             /* Pickup the cleanup routine address.  */ | ||||
|             suspend_cleanup =  thread_ptr -> tx_thread_suspend_cleanup; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Pickup the suspension sequence number that is used later to verify that the | ||||
|                cleanup is still necessary.  */ | ||||
|             suspension_sequence =  thread_ptr -> tx_thread_suspension_sequence; | ||||
| #else | ||||
|  | ||||
|             /* When not interruptable is selected, the suspension sequence is not used - just set to 0.  */ | ||||
|             suspension_sequence =  ((ULONG) 0); | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #endif | ||||
|  | ||||
|             /* Call any cleanup routines.  */ | ||||
|             if (suspend_cleanup != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, there is a function to call.  */ | ||||
|                 (suspend_cleanup)(thread_ptr, suspension_sequence); | ||||
|             } | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Disable interrupts.  */ | ||||
|             TX_DISABLE | ||||
| #endif | ||||
|  | ||||
|             /* Clear the suspending flag.  */ | ||||
|             thread_ptr -> tx_thread_suspending =  TX_FALSE; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #endif | ||||
|  | ||||
|             /* Perform any additional activities for tool or user purpose.  */ | ||||
|             TX_THREAD_TERMINATED_EXTENSION(thread_ptr) | ||||
|  | ||||
| #ifndef TX_DISABLE_NOTIFY_CALLBACKS | ||||
|  | ||||
|             /* Determine if an application callback routine is specified.  */ | ||||
|             if (entry_exit_notify != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Yes, notify application that this thread has exited!  */ | ||||
|                 (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT); | ||||
|             } | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Disable interrupts.  */ | ||||
|             TX_DISABLE | ||||
| #endif | ||||
|         } | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #endif | ||||
|  | ||||
|         /* Determine if the application is using mutexes.  */ | ||||
|         if (_tx_thread_mutex_release != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Yes, call the mutex release function via a function pointer that | ||||
|                is setup during initialization.  */ | ||||
|             (_tx_thread_mutex_release)(thread_ptr); | ||||
|         } | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Disable interrupts.  */ | ||||
|         TX_DISABLE | ||||
| #endif | ||||
|  | ||||
|         /* Enable preemption.  */ | ||||
|         _tx_thread_preempt_disable--; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|     } | ||||
|  | ||||
|     /* Check for preemption.  */ | ||||
|     _tx_thread_system_preempt_check(); | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										190
									
								
								Middlewares/ST/threadx/common/src/tx_thread_time_slice.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								Middlewares/ST/threadx/common/src/tx_thread_time_slice.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,190 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
| #ifndef TX_NO_TIMER | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_timer.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_trace.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_time_slice                               PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function moves the currently executing thread to the end of    */ | ||||
| /*    the threads ready at the same priority level as a result of a       */ | ||||
| /*    time-slice interrupt.  If no other thread of the same priority is   */ | ||||
| /*    ready, this function simply returns.                                */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_interrupt                   Timer interrupt handling      */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Scott Larson             Modified comment(s), and      */ | ||||
| /*                                            opt out of function when    */ | ||||
| /*                                            TX_NO_TIMER is defined,     */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_thread_time_slice(VOID) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
| TX_THREAD       *next_thread_ptr; | ||||
| #endif | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
| ULONG           system_state; | ||||
| UINT            preempt_disable; | ||||
| #endif | ||||
|  | ||||
|     /* Pickup thread pointer.  */ | ||||
|     TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|  | ||||
|     /* Check this thread's stack.  */ | ||||
|     TX_THREAD_STACK_CHECK(thread_ptr) | ||||
|  | ||||
|     /* Set the next thread pointer to NULL.  */ | ||||
|     next_thread_ptr =  TX_NULL; | ||||
| #endif | ||||
|  | ||||
|     /* Lockout interrupts while the time-slice is evaluated.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Clear the expired time-slice flag.  */ | ||||
|     _tx_timer_expired_time_slice =  TX_FALSE; | ||||
|  | ||||
|     /* Make sure the thread pointer is valid.  */ | ||||
|     if (thread_ptr != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Make sure the thread is still active, i.e. not suspended.  */ | ||||
|         if (thread_ptr -> tx_thread_state == TX_READY) | ||||
|         { | ||||
|  | ||||
|             /* Setup a fresh time-slice for the thread.  */ | ||||
|             thread_ptr -> tx_thread_time_slice =  thread_ptr -> tx_thread_new_time_slice; | ||||
|  | ||||
|             /* Reset the actual time-slice variable.  */ | ||||
|             _tx_timer_time_slice =  thread_ptr -> tx_thread_time_slice; | ||||
|  | ||||
|             /* Determine if there is another thread at the same priority and preemption-threshold | ||||
|                is not set.  Preemption-threshold overrides time-slicing.  */ | ||||
|             if (thread_ptr -> tx_thread_ready_next != thread_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Check to see if preemption-threshold is not being used.  */ | ||||
|                 if (thread_ptr -> tx_thread_priority == thread_ptr -> tx_thread_preempt_threshold) | ||||
|                 { | ||||
|  | ||||
|                     /* Preemption-threshold is not being used by this thread.  */ | ||||
|  | ||||
|                     /* There is another thread at this priority, make it the highest at | ||||
|                        this priority level.  */ | ||||
|                     _tx_thread_priority_list[thread_ptr -> tx_thread_priority] =  thread_ptr -> tx_thread_ready_next; | ||||
|  | ||||
|                     /* Designate the highest priority thread as the one to execute.  Don't use this | ||||
|                        thread's priority as an index just in case a higher priority thread is now | ||||
|                        ready!  */ | ||||
|                     _tx_thread_execute_ptr =  _tx_thread_priority_list[_tx_thread_highest_priority]; | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                     /* Increment the thread's time-slice counter.  */ | ||||
|                     thread_ptr -> tx_thread_performance_time_slice_count++; | ||||
|  | ||||
|                     /* Increment the total number of thread time-slice operations.  */ | ||||
|                     _tx_thread_performance_time_slice_count++; | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|  | ||||
|                     /* Pickup the next execute pointer.  */ | ||||
|                     next_thread_ptr =  _tx_thread_execute_ptr; | ||||
| #endif | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|     /* Pickup the volatile information.  */ | ||||
|     system_state =  TX_THREAD_GET_SYSTEM_STATE(); | ||||
|     preempt_disable =  _tx_thread_preempt_disable; | ||||
|  | ||||
|     /* Insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIME_SLICE, _tx_thread_execute_ptr, system_state, preempt_disable, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), TX_TRACE_INTERNAL_EVENTS) | ||||
| #endif | ||||
|  | ||||
|     /* Restore previous interrupt posture.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
| #ifdef TX_ENABLE_STACK_CHECKING | ||||
|  | ||||
|     /* Determine if there is a next thread pointer to perform stack checking on.  */ | ||||
|     if (next_thread_ptr != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Yes, check this thread's stack.  */ | ||||
|         TX_THREAD_STACK_CHECK(next_thread_ptr) | ||||
|     } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										119
									
								
								Middlewares/ST/threadx/common/src/tx_thread_time_slice_change.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								Middlewares/ST/threadx/common/src/tx_thread_time_slice_change.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_time_slice_change                        PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function processes thread time slice change requests.  The     */ | ||||
| /*    previous time slice is returned to the caller.  If the new request  */ | ||||
| /*    is made for an executing thread, it is also placed in the actual    */ | ||||
| /*    time-slice countdown variable.                                      */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                            Pointer to thread             */ | ||||
| /*    new_time_slice                        New time slice                */ | ||||
| /*    old_time_slice                        Old time slice                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Service return status         */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_thread_time_slice_change(TX_THREAD *thread_ptr, ULONG new_time_slice, ULONG *old_time_slice) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *current_thread; | ||||
|  | ||||
|  | ||||
|     /* Lockout interrupts while the thread is being resumed.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_TIME_SLICE_CHANGE, thread_ptr, new_time_slice, thread_ptr -> tx_thread_new_time_slice, 0, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_THREAD_TIME_SLICE_CHANGE_INSERT | ||||
|  | ||||
|     /* Return the old time slice.  */ | ||||
|     *old_time_slice =  thread_ptr -> tx_thread_new_time_slice; | ||||
|  | ||||
|     /* Setup the new time-slice.  */ | ||||
|     thread_ptr -> tx_thread_time_slice =      new_time_slice; | ||||
|     thread_ptr -> tx_thread_new_time_slice =  new_time_slice; | ||||
|  | ||||
|     /* Pickup thread pointer.  */ | ||||
|     TX_THREAD_GET_CURRENT(current_thread) | ||||
|  | ||||
|     /* Determine if this thread is the currently executing thread.  */ | ||||
|     if (thread_ptr == current_thread) | ||||
|     { | ||||
|  | ||||
|         /* Yes, update the time-slice countdown variable.  */ | ||||
|         _tx_timer_time_slice =  new_time_slice; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										167
									
								
								Middlewares/ST/threadx/common/src/tx_thread_timeout.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								Middlewares/ST/threadx/common/src/tx_thread_timeout.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,167 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_timeout                                  PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function handles thread timeout processing.  Timeouts occur in */ | ||||
| /*    two flavors, namely the thread sleep timeout and all other service  */ | ||||
| /*    call timeouts.  Thread sleep timeouts are processed locally, while  */ | ||||
| /*    the others are processed by the appropriate suspension clean-up     */ | ||||
| /*    service.                                                            */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    timeout_input                         Contains the thread pointer   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    Suspension Cleanup Functions                                        */ | ||||
| /*    _tx_thread_system_resume          Resume thread                     */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_expiration_process          Timer expiration function     */ | ||||
| /*    _tx_timer_thread_entry                Timer thread function         */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_thread_timeout(ULONG timeout_input) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_THREAD       *thread_ptr; | ||||
| VOID            (*suspend_cleanup)(struct TX_THREAD_STRUCT *suspend_thread_ptr, ULONG suspension_sequence); | ||||
| ULONG           suspension_sequence; | ||||
|  | ||||
|  | ||||
|     /* Pickup the thread pointer.  */ | ||||
|     TX_THREAD_TIMEOUT_POINTER_SETUP(thread_ptr) | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Determine how the thread is currently suspended.  */ | ||||
|     if (thread_ptr -> tx_thread_state == TX_SLEEP) | ||||
|     { | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Resume the thread!  */ | ||||
|         _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #else | ||||
|  | ||||
|         /* Increment the disable preemption flag.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Lift the suspension on the sleeping thread.  */ | ||||
|         _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Process all other suspension timeouts.  */ | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|         /* Increment the total number of thread timeouts.  */ | ||||
|         _tx_thread_performance_timeout_count++; | ||||
|  | ||||
|         /* Increment the number of timeouts for this thread.  */ | ||||
|         thread_ptr -> tx_thread_performance_timeout_count++; | ||||
| #endif | ||||
|  | ||||
|         /* Pickup the cleanup routine address.  */ | ||||
|         suspend_cleanup =  thread_ptr -> tx_thread_suspend_cleanup; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Pickup the suspension sequence number that is used later to verify that the | ||||
|            cleanup is still necessary.  */ | ||||
|         suspension_sequence =  thread_ptr -> tx_thread_suspension_sequence; | ||||
| #else | ||||
|  | ||||
|         /* When not interruptable is selected, the suspension sequence is not used - just set to 0.  */ | ||||
|         suspension_sequence =  ((ULONG) 0); | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #endif | ||||
|  | ||||
|         /* Call any cleanup routines.  */ | ||||
|         if (suspend_cleanup != TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Yes, there is a function to call.  */ | ||||
|             (suspend_cleanup)(thread_ptr, suspension_sequence); | ||||
|         } | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
| #endif | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										247
									
								
								Middlewares/ST/threadx/common/src/tx_thread_wait_abort.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								Middlewares/ST/threadx/common/src/tx_thread_wait_abort.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,247 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Thread                                                              */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_wait_abort                               PORTABLE C      */ | ||||
| /*                                                           6.2.1        */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function aborts the wait condition that the specified thread   */ | ||||
| /*    is in - regardless of what object the thread is waiting on - and    */ | ||||
| /*    returns a TX_WAIT_ABORTED status to the specified thread.           */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    thread_ptr                            Thread to abort the wait on   */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                                Return completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    Suspension Cleanup Functions                                        */ | ||||
| /*    _tx_thread_system_resume                                            */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020      William E. Lamie        Initial Version 6.0           */ | ||||
| /*  09-30-2020      Yuxin Zhou              Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*  03-08-2023      Scott Larson            Check if thread is coming out */ | ||||
| /*                                            of suspension elsewhere,    */ | ||||
| /*                                            resulting in version 6.2.1  */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_thread_wait_abort(TX_THREAD  *thread_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| VOID            (*suspend_cleanup)(struct TX_THREAD_STRUCT *suspend_thread_ptr, ULONG suspension_sequence); | ||||
| UINT            status; | ||||
| ULONG           suspension_sequence; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_WAIT_ABORT, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_THREAD_WAIT_ABORT_INSERT | ||||
|  | ||||
|     /* Determine if the thread is currently suspended.  */ | ||||
|     if (thread_ptr -> tx_thread_state < TX_SLEEP) | ||||
|     { | ||||
|  | ||||
|         /* Thread is either ready, completed, terminated, or in a pure | ||||
|            suspension condition.  */ | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Just return with an error message to indicate that | ||||
|            nothing was done.  */ | ||||
|         status =  TX_WAIT_ABORT_ERROR; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Check for a sleep condition.  */ | ||||
|         if (thread_ptr -> tx_thread_state == TX_SLEEP) | ||||
|         { | ||||
|  | ||||
|             /* Set the state to terminated.  */ | ||||
|             thread_ptr -> tx_thread_state =    TX_SUSPENDED; | ||||
|  | ||||
|             /* Set the TX_WAIT_ABORTED status in the thread that is | ||||
|                sleeping.  */ | ||||
|             thread_ptr -> tx_thread_suspend_status =  TX_WAIT_ABORTED; | ||||
|  | ||||
|             /* Make sure there isn't a suspend cleanup routine.  */ | ||||
|             thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Increment the disable preemption flag.  */ | ||||
|             _tx_thread_preempt_disable++; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #endif | ||||
|         } | ||||
|         else if(thread_ptr -> tx_thread_suspend_cleanup == TX_NULL) | ||||
|         { | ||||
|             /* Thread is coming out of suspension elsewhere.  */ | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|             /* Increment the disable preemption flag.  */ | ||||
|             _tx_thread_preempt_disable++; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #endif | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Process all other suspension timeouts.  */ | ||||
|  | ||||
|             /* Set the state to suspended.  */ | ||||
|             thread_ptr -> tx_thread_state =    TX_SUSPENDED; | ||||
|  | ||||
|             /* Pickup the cleanup routine address.  */ | ||||
|             suspend_cleanup =  thread_ptr -> tx_thread_suspend_cleanup; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Pickup the suspension sequence number that is used later to verify that the | ||||
|                cleanup is still necessary.  */ | ||||
|             suspension_sequence =  thread_ptr -> tx_thread_suspension_sequence; | ||||
| #else | ||||
|  | ||||
|             /* When not interruptable is selected, the suspension sequence is not used - just set to 0.  */ | ||||
|             suspension_sequence =  ((ULONG) 0); | ||||
| #endif | ||||
|  | ||||
|             /* Set the TX_WAIT_ABORTED status in the thread that was | ||||
|                suspended.  */ | ||||
|             thread_ptr -> tx_thread_suspend_status =  TX_WAIT_ABORTED; | ||||
|  | ||||
| #ifndef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Increment the disable preemption flag.  */ | ||||
|             _tx_thread_preempt_disable++; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #endif | ||||
|  | ||||
|             /* Call cleanup routine.  */ | ||||
|             (suspend_cleanup)(thread_ptr, suspension_sequence); | ||||
|         } | ||||
|  | ||||
|         /* If the abort of the thread wait was successful, if so resume the thread.  */ | ||||
|         if (thread_ptr -> tx_thread_suspend_status == TX_WAIT_ABORTED) | ||||
|         { | ||||
|  | ||||
| #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|             /* Increment the total number of thread wait aborts.  */ | ||||
|             _tx_thread_performance_wait_abort_count++; | ||||
|  | ||||
|             /* Increment this thread's wait abort count.  */ | ||||
|             thread_ptr -> tx_thread_performance_wait_abort_count++; | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Resume the thread!  */ | ||||
|             _tx_thread_system_ni_resume(thread_ptr); | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #else | ||||
|  | ||||
|             /* Lift the suspension on the previously waiting thread.  */ | ||||
|             _tx_thread_system_resume(thread_ptr); | ||||
| #endif | ||||
|  | ||||
|             /* Return a successful status.  */ | ||||
|             status =  TX_SUCCESS; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
| #else | ||||
|  | ||||
|             /* Disable interrupts.  */ | ||||
|             TX_DISABLE | ||||
|  | ||||
|             /* Decrement the disable preemption flag.  */ | ||||
|             _tx_thread_preempt_disable--; | ||||
|  | ||||
|             /* Restore interrupts.  */ | ||||
|             TX_RESTORE | ||||
| #endif | ||||
|  | ||||
|             /* Return with an error message to indicate that | ||||
|                nothing was done.  */ | ||||
|             status =  TX_WAIT_ABORT_ERROR; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										104
									
								
								Middlewares/ST/threadx/common/src/tx_time_get.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								Middlewares/ST/threadx/common/src/tx_time_get.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Timer                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_time_get                                        PORTABLE C      */ | ||||
| /*                                                           6.1.3        */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function retrieves the internal, free-running, system clock    */ | ||||
| /*    and returns it to the caller.                                       */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_system_clock            Returns the system clock value    */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*  12-31-2020     Andres Mlinar            Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1.3  */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| ULONG  _tx_time_get(VOID) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
| ULONG   another_temp_time =  ((ULONG) 0); | ||||
| #endif | ||||
| ULONG   temp_time; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Pickup the system clock time.  */ | ||||
|     temp_time =  _tx_timer_system_clock; | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIME_GET, TX_ULONG_TO_POINTER_CONVERT(temp_time), TX_POINTER_TO_ULONG_CONVERT(&another_temp_time), 0, 0, TX_TRACE_TIME_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_TIME_GET_INSERT | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return the time.  */ | ||||
|     return(temp_time); | ||||
| } | ||||
|  | ||||
							
								
								
									
										94
									
								
								Middlewares/ST/threadx/common/src/tx_time_set.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								Middlewares/ST/threadx/common/src/tx_time_set.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Timer                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_time_set                                        PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function modifies the internal, free-running, system clock     */ | ||||
| /*    as specified by the caller.                                         */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    new_time                              New time value                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_time_set(ULONG new_time) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIME_SET, TX_ULONG_TO_POINTER_CONVERT(new_time), 0, 0, 0, TX_TRACE_TIME_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_TIME_SET_INSERT | ||||
|  | ||||
|     /* Set the system clock time.  */ | ||||
|     _tx_timer_system_clock =  new_time; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
| } | ||||
|  | ||||
							
								
								
									
										137
									
								
								Middlewares/ST/threadx/common/src/tx_timer_activate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								Middlewares/ST/threadx/common/src/tx_timer_activate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,137 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Timer                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_timer.h" | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
| #include "tx_trace.h" | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_activate                                  PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function activates the specified application timer.            */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    timer_ptr                         Pointer to timer control block    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Always returns success            */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_system_activate         Actual timer activation function  */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_timer_activate(TX_TIMER *timer_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| UINT        status; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to put the timer on the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_TRACE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_ACTIVATE, timer_ptr, 0, 0, 0, TX_TRACE_TIMER_EVENTS) | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_ENABLE_EVENT_LOGGING | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_TIMER_ACTIVATE_INSERT | ||||
| #endif | ||||
|  | ||||
|     /* Check for an already active timer.  */ | ||||
|     if (timer_ptr -> tx_timer_internal.tx_timer_internal_list_head != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Timer is already active, return an error.  */ | ||||
|         status =  TX_ACTIVATE_ERROR; | ||||
|     } | ||||
|  | ||||
|     /* Check for a timer with a zero expiration.  */ | ||||
|     else if (timer_ptr -> tx_timer_internal.tx_timer_internal_remaining_ticks == ((ULONG) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Timer is being activated with a zero expiration.  */ | ||||
|         status =  TX_ACTIVATE_ERROR; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
| #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|         /* Increment the total activations counter.  */ | ||||
|         _tx_timer_performance_activate_count++; | ||||
|  | ||||
|         /* Increment the number of activations on this timer.  */ | ||||
|         timer_ptr -> tx_timer_performance_activate_count++; | ||||
| #endif | ||||
|  | ||||
|         /* Call actual activation function.  */ | ||||
|         _tx_timer_system_activate(&(timer_ptr -> tx_timer_internal)); | ||||
|  | ||||
|         /* Return a successful status.  */ | ||||
|         status =  TX_SUCCESS; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										105
									
								
								Middlewares/ST/threadx/common/src/tx_timer_change.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								Middlewares/ST/threadx/common/src/tx_timer_change.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Timer                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_change                                    PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function modifies an application timer as specified by the     */ | ||||
| /*    input.                                                              */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    timer_ptr                         Pointer to timer control block    */ | ||||
| /*    initial_ticks                     Initial expiration ticks          */ | ||||
| /*    reschedule_ticks                  Reschedule ticks                  */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_timer_change(TX_TIMER *timer_ptr, ULONG initial_ticks, ULONG reschedule_ticks) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to put the timer on the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_CHANGE, timer_ptr, initial_ticks, reschedule_ticks, 0, TX_TRACE_TIMER_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_TIMER_CHANGE_INSERT | ||||
|  | ||||
|     /* Determine if the timer is active.  */ | ||||
|     if (timer_ptr -> tx_timer_internal.tx_timer_internal_list_head == TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Setup the new expiration fields.  */ | ||||
|         timer_ptr -> tx_timer_internal.tx_timer_internal_remaining_ticks =      initial_ticks; | ||||
|         timer_ptr -> tx_timer_internal.tx_timer_internal_re_initialize_ticks =  reschedule_ticks; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										169
									
								
								Middlewares/ST/threadx/common/src/tx_timer_create.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								Middlewares/ST/threadx/common/src/tx_timer_create.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,169 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Timer                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_create                                    PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function creates an application timer from the specified       */ | ||||
| /*    input.                                                              */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    timer_ptr                         Pointer to timer control block    */ | ||||
| /*    name_ptr                          Pointer to timer name             */ | ||||
| /*    expiration_function               Application expiration function   */ | ||||
| /*    initial_ticks                     Initial expiration ticks          */ | ||||
| /*    reschedule_ticks                  Reschedule ticks                  */ | ||||
| /*    auto_activate                     Automatic activation flag         */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_system_activate         Timer activation function         */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, | ||||
|             VOID (*expiration_function)(ULONG id), ULONG expiration_input, | ||||
|             ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_TIMER        *next_timer; | ||||
| TX_TIMER        *previous_timer; | ||||
|  | ||||
|  | ||||
|     /* Initialize timer control block to all zeros.  */ | ||||
|     TX_MEMSET(timer_ptr, 0, (sizeof(TX_TIMER))); | ||||
|  | ||||
|     /* Setup the basic timer fields.  */ | ||||
|     timer_ptr -> tx_timer_name =                                            name_ptr; | ||||
|     timer_ptr -> tx_timer_internal.tx_timer_internal_remaining_ticks =      initial_ticks; | ||||
|     timer_ptr -> tx_timer_internal.tx_timer_internal_re_initialize_ticks =  reschedule_ticks; | ||||
|     timer_ptr -> tx_timer_internal.tx_timer_internal_timeout_function =     expiration_function; | ||||
|     timer_ptr -> tx_timer_internal.tx_timer_internal_timeout_param =        expiration_input; | ||||
|  | ||||
|     /* Disable interrupts to put the timer on the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Setup the timer ID to make it valid.  */ | ||||
|     timer_ptr -> tx_timer_id =  TX_TIMER_ID; | ||||
|  | ||||
|     /* Place the timer on the list of created application timers.  First, | ||||
|        check for an empty list.  */ | ||||
|     if (_tx_timer_created_count == TX_EMPTY) | ||||
|     { | ||||
|  | ||||
|         /* The created timer list is empty.  Add timer to empty list.  */ | ||||
|         _tx_timer_created_ptr =                   timer_ptr; | ||||
|         timer_ptr -> tx_timer_created_next =      timer_ptr; | ||||
|         timer_ptr -> tx_timer_created_previous =  timer_ptr; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* This list is not NULL, add to the end of the list.  */ | ||||
|         next_timer =  _tx_timer_created_ptr; | ||||
|         previous_timer =  next_timer -> tx_timer_created_previous; | ||||
|  | ||||
|         /* Place the new timer in the list.  */ | ||||
|         next_timer -> tx_timer_created_previous =  timer_ptr; | ||||
|         previous_timer -> tx_timer_created_next =    timer_ptr; | ||||
|  | ||||
|         /* Setup this timer's created links.  */ | ||||
|         timer_ptr -> tx_timer_created_previous =  previous_timer; | ||||
|         timer_ptr -> tx_timer_created_next =      next_timer; | ||||
|     } | ||||
|  | ||||
|     /* Increment the number of created timers.  */ | ||||
|     _tx_timer_created_count++; | ||||
|  | ||||
|     /* Optional timer create extended processing.  */ | ||||
|     TX_TIMER_CREATE_EXTENSION(timer_ptr) | ||||
|  | ||||
|     /* If trace is enabled, register this object.  */ | ||||
|     TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_TIMER, timer_ptr, name_ptr, initial_ticks, reschedule_ticks) | ||||
|  | ||||
|     /* If trace is enabled, insert this call in the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_CREATE, timer_ptr, initial_ticks, reschedule_ticks, auto_activate, TX_TRACE_TIMER_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_TIMER_CREATE_INSERT | ||||
|  | ||||
|     /* Determine if this timer needs to be activated.  */ | ||||
|     if (auto_activate == TX_AUTO_ACTIVATE) | ||||
|     { | ||||
|  | ||||
| #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|         /* Increment the total activations counter.  */ | ||||
|         _tx_timer_performance_activate_count++; | ||||
|  | ||||
|         /* Increment the number of activations on this timer.  */ | ||||
|         timer_ptr -> tx_timer_performance_activate_count++; | ||||
| #endif | ||||
|  | ||||
|         /* Call actual activation function.  */ | ||||
|         _tx_timer_system_activate(&(timer_ptr -> tx_timer_internal)); | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										252
									
								
								Middlewares/ST/threadx/common/src/tx_timer_deactivate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								Middlewares/ST/threadx/common/src/tx_timer_deactivate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,252 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Timer                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_deactivate                                PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function deactivates the specified application timer.          */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    timer_ptr                         Pointer to timer control block    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Always returns success            */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_timer_deactivate(TX_TIMER *timer_ptr) | ||||
| { | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_TIMER_INTERNAL   *internal_ptr; | ||||
| TX_TIMER_INTERNAL   **list_head; | ||||
| TX_TIMER_INTERNAL   *next_timer; | ||||
| TX_TIMER_INTERNAL   *previous_timer; | ||||
| ULONG               ticks_left; | ||||
| UINT                active_timer_list; | ||||
|  | ||||
|  | ||||
|     /* Setup internal timer pointer.  */ | ||||
|     internal_ptr =  &(timer_ptr -> tx_timer_internal); | ||||
|  | ||||
|     /* Disable interrupts while the remaining time before expiration is | ||||
|        calculated.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Increment the total deactivations counter.  */ | ||||
|     _tx_timer_performance_deactivate_count++; | ||||
|  | ||||
|     /* Increment the number of deactivations on this timer.  */ | ||||
|     timer_ptr -> tx_timer_performance_deactivate_count++; | ||||
| #endif | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_DEACTIVATE, timer_ptr, TX_POINTER_TO_ULONG_CONVERT(&ticks_left), 0, 0, TX_TRACE_TIMER_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_TIMER_DEACTIVATE_INSERT | ||||
|  | ||||
|     /* Pickup the list head.  */ | ||||
|     list_head =  internal_ptr -> tx_timer_internal_list_head; | ||||
|  | ||||
|     /* Is the timer active?  */ | ||||
|     if (list_head != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Default the active timer list flag to false.  */ | ||||
|         active_timer_list =  TX_FALSE; | ||||
|  | ||||
|         /* Determine if the head pointer is within the timer expiration list.  */ | ||||
|         if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(list_head) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_start)) | ||||
|         { | ||||
|  | ||||
|             /* Now check to make sure the list head is before the end of the list.  */ | ||||
|             if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(list_head) < TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_end)) | ||||
|             { | ||||
|  | ||||
|                 /* Set the active timer list flag to true.  */ | ||||
|                 active_timer_list =  TX_TRUE; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Determine if the timer is on active timer list.  */ | ||||
|         if (active_timer_list == TX_TRUE) | ||||
|         { | ||||
|  | ||||
|             /* This timer is active and has not yet expired.  */ | ||||
|  | ||||
|             /* Calculate the amount of time that has elapsed since the timer | ||||
|                was activated.  */ | ||||
|  | ||||
|             /* Is this timer's entry after the current timer pointer?  */ | ||||
|             if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(list_head) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_current_ptr)) | ||||
|             { | ||||
|  | ||||
|                 /* Calculate ticks left to expiration - just the difference between this | ||||
|                    timer's entry and the current timer pointer.  */ | ||||
|                 ticks_left =  (ULONG) (TX_TIMER_POINTER_DIF(list_head,_tx_timer_current_ptr)) + ((ULONG) 1); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Calculate the ticks left with a wrapped list condition.  */ | ||||
|                 ticks_left =  (ULONG) (TX_TIMER_POINTER_DIF(list_head,_tx_timer_list_start)); | ||||
|  | ||||
|                 ticks_left =  ticks_left + (ULONG) ((TX_TIMER_POINTER_DIF(_tx_timer_list_end, _tx_timer_current_ptr)) + ((ULONG) 1)); | ||||
|             } | ||||
|  | ||||
|             /* Adjust the remaining ticks accordingly.  */ | ||||
|             if (internal_ptr -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES) | ||||
|             { | ||||
|  | ||||
|                 /* Subtract off the last full pass through the timer list and add the | ||||
|                    time left.  */ | ||||
|                 internal_ptr -> tx_timer_internal_remaining_ticks = | ||||
|                         (internal_ptr -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES) + ticks_left; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Just put the ticks left into the timer's remaining ticks.  */ | ||||
|                 internal_ptr -> tx_timer_internal_remaining_ticks =  ticks_left; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Determine if this is timer has just expired.  */ | ||||
|             if (_tx_timer_expired_timer_ptr != internal_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* No, it hasn't expired. Now check for remaining time greater than the list | ||||
|                    size.  */ | ||||
|                 if (internal_ptr -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES) | ||||
|                 { | ||||
|  | ||||
|                     /* Adjust the remaining ticks.  */ | ||||
|                     internal_ptr -> tx_timer_internal_remaining_ticks = | ||||
|                                             internal_ptr -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* Set the remaining time to the reactivation time.  */ | ||||
|                     internal_ptr -> tx_timer_internal_remaining_ticks =  internal_ptr -> tx_timer_internal_re_initialize_ticks; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Set the remaining time to the reactivation time.  */ | ||||
|                 internal_ptr -> tx_timer_internal_remaining_ticks =  internal_ptr -> tx_timer_internal_re_initialize_ticks; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Pickup the next timer.  */ | ||||
|         next_timer =  internal_ptr -> tx_timer_internal_active_next; | ||||
|  | ||||
|         /* See if this is the only timer in the list.  */ | ||||
|         if (internal_ptr == next_timer) | ||||
|         { | ||||
|  | ||||
|             /* Yes, the only timer on the list.  */ | ||||
|  | ||||
|             /* Determine if the head pointer needs to be updated.  */ | ||||
|             if (*(list_head) == internal_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Update the head pointer.  */ | ||||
|                 *(list_head) =  TX_NULL; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* At least one more timer is on the same expiration list.  */ | ||||
|  | ||||
|             /* Update the links of the adjacent timers.  */ | ||||
|             previous_timer =                                   internal_ptr -> tx_timer_internal_active_previous; | ||||
|             next_timer -> tx_timer_internal_active_previous =  previous_timer; | ||||
|             previous_timer -> tx_timer_internal_active_next =  next_timer; | ||||
|  | ||||
|             /* Determine if the head pointer needs to be updated.  */ | ||||
|             if (*(list_head) == internal_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Update the next timer in the list with the list head | ||||
|                    pointer.  */ | ||||
|                 next_timer -> tx_timer_internal_list_head =  list_head; | ||||
|  | ||||
|                 /* Update the head pointer.  */ | ||||
|                 *(list_head) =  next_timer; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Clear the timer's list head pointer.  */ | ||||
|         internal_ptr -> tx_timer_internal_list_head =  TX_NULL; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts to previous posture.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										144
									
								
								Middlewares/ST/threadx/common/src/tx_timer_delete.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								Middlewares/ST/threadx/common/src/tx_timer_delete.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Timer                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_delete                                    PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function deletes the specified application timer.              */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    timer_ptr                         Pointer to timer control block    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Successful completion status      */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_system_deactivate       Timer deactivation function       */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_timer_delete(TX_TIMER *timer_ptr) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_TIMER        *next_timer; | ||||
| TX_TIMER        *previous_timer; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts to remove the timer from the created list.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Determine if the timer needs to be deactivated.  */ | ||||
|     if (timer_ptr -> tx_timer_internal.tx_timer_internal_list_head != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Yes, deactivate the timer before it is deleted.  */ | ||||
|         _tx_timer_system_deactivate(&(timer_ptr -> tx_timer_internal)); | ||||
|     } | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_DELETE, timer_ptr, 0, 0, 0, TX_TRACE_TIMER_EVENTS) | ||||
|  | ||||
|     /* Optional timer delete extended processing.  */ | ||||
|     TX_TIMER_DELETE_EXTENSION(timer_ptr) | ||||
|  | ||||
|     /* If trace is enabled, unregister this object.  */ | ||||
|     TX_TRACE_OBJECT_UNREGISTER(timer_ptr) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_TIMER_DELETE_INSERT | ||||
|  | ||||
|     /* Clear the timer ID to make it invalid.  */ | ||||
|     timer_ptr -> tx_timer_id =  TX_CLEAR_ID; | ||||
|  | ||||
|     /* Decrement the number of created timers.  */ | ||||
|     _tx_timer_created_count--; | ||||
|  | ||||
|     /* See if the timer is the only one on the list.  */ | ||||
|     if (_tx_timer_created_count == TX_EMPTY) | ||||
|     { | ||||
|  | ||||
|         /* Only created timer, just set the created list to NULL.  */ | ||||
|         _tx_timer_created_ptr =  TX_NULL; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Link-up the neighbors.  */ | ||||
|         next_timer =                               timer_ptr -> tx_timer_created_next; | ||||
|         previous_timer =                           timer_ptr -> tx_timer_created_previous; | ||||
|         next_timer -> tx_timer_created_previous =  previous_timer; | ||||
|         previous_timer -> tx_timer_created_next =  next_timer; | ||||
|  | ||||
|         /* See if we have to update the created list head pointer.  */ | ||||
|         if (_tx_timer_created_ptr == timer_ptr) | ||||
|         { | ||||
|  | ||||
|             /* Yes, move the head pointer to the next link. */ | ||||
|             _tx_timer_created_ptr =  next_timer; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h.  */ | ||||
|     TX_TIMER_DELETE_PORT_COMPLETION(timer_ptr) | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return TX_SUCCESS.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										483
									
								
								Middlewares/ST/threadx/common/src/tx_timer_expiration_process.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										483
									
								
								Middlewares/ST/threadx/common/src/tx_timer_expiration_process.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,483 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Timer                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
| #ifndef TX_NO_TIMER | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_timer.h" | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_expiration_process                        PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function processes thread and application timer expirations.   */ | ||||
| /*    It is called from the _tx_timer_interrupt handler and either        */ | ||||
| /*    processes the timer expiration in the ISR or defers to the system   */ | ||||
| /*    timer thread. The actual processing is determined during            */ | ||||
| /*    compilation.                                                        */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Thread resume processing          */ | ||||
| /*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */ | ||||
| /*    _tx_timer_system_activate         Timer reactivate processing       */ | ||||
| /*    Timer Expiration Function                                           */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_interrupt               Timer interrupt handler           */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Scott Larson             Modified comment(s), and      */ | ||||
| /*                                            opt out of function when    */ | ||||
| /*                                            TX_NO_TIMER is defined,     */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_timer_expiration_process(VOID) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| #ifdef TX_TIMER_PROCESS_IN_ISR | ||||
|  | ||||
| TX_TIMER_INTERNAL           *expired_timers; | ||||
| TX_TIMER_INTERNAL           *reactivate_timer; | ||||
| TX_TIMER_INTERNAL           *next_timer; | ||||
| TX_TIMER_INTERNAL           *previous_timer; | ||||
| #ifdef TX_REACTIVATE_INLINE | ||||
| TX_TIMER_INTERNAL           **timer_list;               /* Timer list pointer           */ | ||||
| UINT                        expiration_time;            /* Value used for pointer offset*/ | ||||
| ULONG                       delta; | ||||
| #endif | ||||
| TX_TIMER_INTERNAL           *current_timer; | ||||
| VOID                        (*timeout_function)(ULONG id); | ||||
| ULONG                       timeout_param =  ((ULONG) 0); | ||||
| #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO | ||||
| TX_TIMER                    *timer_ptr; | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_TIMER_PROCESS_IN_ISR | ||||
|  | ||||
|     /* Don't process in the ISR, wakeup the system timer thread to process the | ||||
|        timer expiration.  */ | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|     /* Resume the thread!  */ | ||||
|     _tx_thread_system_ni_resume(&_tx_timer_thread); | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
| #else | ||||
|  | ||||
|     /* Increment the preempt disable flag.  */ | ||||
|     _tx_thread_preempt_disable++; | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Call the system resume function to activate the timer thread.  */ | ||||
|     _tx_thread_system_resume(&_tx_timer_thread); | ||||
| #endif | ||||
|  | ||||
| #else | ||||
|  | ||||
|     /* Process the timer expiration directly in the ISR. This increases the interrupt | ||||
|        processing, however, it eliminates the need for a system timer thread and associated | ||||
|        resources.  */ | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* Determine if the timer processing is already active.  This needs to be checked outside | ||||
|        of the processing loop because it remains set throughout nested timer interrupt conditions.  */ | ||||
|     if (_tx_timer_processing_active == TX_FALSE) | ||||
|     { | ||||
|  | ||||
|         /* Timer processing is not nested.  */ | ||||
|  | ||||
|         /* Determine if the timer expiration has already been cleared.  */ | ||||
|         if (_tx_timer_expired != ((UINT) 0)) | ||||
|         { | ||||
|  | ||||
|             /* Proceed with timer processing.  */ | ||||
|  | ||||
|             /* Set the timer interrupt processing active flag.  */ | ||||
|             _tx_timer_processing_active =  TX_TRUE; | ||||
|  | ||||
|             /* Now go into an infinite loop to process timer expirations.  */ | ||||
|             do | ||||
|             { | ||||
|  | ||||
|                 /* First, move the current list pointer and clear the timer | ||||
|                    expired value.  This allows the interrupt handling portion | ||||
|                    to continue looking for timer expirations.  */ | ||||
|  | ||||
|                 /* Save the current timer expiration list pointer.  */ | ||||
|                 expired_timers =  *_tx_timer_current_ptr; | ||||
|  | ||||
|                 /* Modify the head pointer in the first timer in the list, if there | ||||
|                    is one!  */ | ||||
|                 if (expired_timers != TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     expired_timers -> tx_timer_internal_list_head =  &expired_timers; | ||||
|                 } | ||||
|  | ||||
|                 /* Set the current list pointer to NULL.  */ | ||||
|                 *_tx_timer_current_ptr =  TX_NULL; | ||||
|  | ||||
|                 /* Move the current pointer up one timer entry wrap if we get to | ||||
|                    the end of the list.  */ | ||||
|                 _tx_timer_current_ptr =  TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, 1); | ||||
|                 if (_tx_timer_current_ptr == _tx_timer_list_end) | ||||
|                 { | ||||
|  | ||||
|                     _tx_timer_current_ptr =  _tx_timer_list_start; | ||||
|                 } | ||||
|  | ||||
|                 /* Clear the expired flag.  */ | ||||
|                 _tx_timer_expired =  TX_FALSE; | ||||
|  | ||||
|                 /* Restore interrupts temporarily.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Disable interrupts again.  */ | ||||
|                 TX_DISABLE | ||||
|  | ||||
|                 /* Next, process the expiration of the associated timers at this | ||||
|                    time slot.  */ | ||||
|                 while (expired_timers != TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     /* Something is on the list.  Remove it and process the expiration.  */ | ||||
|                     current_timer =  expired_timers; | ||||
|  | ||||
|                     /* Pickup the next timer.  */ | ||||
|                     next_timer =  expired_timers -> tx_timer_internal_active_next; | ||||
|  | ||||
|                     /* Set the reactivate timer to NULL.  */ | ||||
|                     reactivate_timer =  TX_NULL; | ||||
|  | ||||
|                     /* Determine if this is the only timer.  */ | ||||
|                     if (current_timer == next_timer) | ||||
|                     { | ||||
|  | ||||
|                         /* Yes, this is the only timer in the list.  */ | ||||
|  | ||||
|                         /* Set the head pointer to NULL.  */ | ||||
|                         expired_timers =  TX_NULL; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|  | ||||
|                         /* No, not the only expired timer.  */ | ||||
|  | ||||
|                         /* Remove this timer from the expired list.  */ | ||||
|                         previous_timer =                                   current_timer -> tx_timer_internal_active_previous; | ||||
|                         next_timer -> tx_timer_internal_active_previous =  previous_timer; | ||||
|                         previous_timer -> tx_timer_internal_active_next =  next_timer; | ||||
|  | ||||
|                         /* Modify the next timer's list head to point at the current list head.  */ | ||||
|                         next_timer -> tx_timer_internal_list_head =  &expired_timers; | ||||
|  | ||||
|                         /* Set the list head pointer.  */ | ||||
|                         expired_timers =  next_timer; | ||||
|                     } | ||||
|  | ||||
|                     /* In any case, the timer is now off of the expired list.  */ | ||||
|  | ||||
|                     /* Determine if the timer has expired or if it is just a really | ||||
|                        big timer that needs to be placed in the list again.  */ | ||||
|                     if (current_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES) | ||||
|                     { | ||||
|  | ||||
|                         /* Timer is bigger than the timer entries and must be | ||||
|                            rescheduled.  */ | ||||
|  | ||||
| #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                         /* Increment the total expiration adjustments counter.  */ | ||||
|                         _tx_timer_performance__expiration_adjust_count++; | ||||
|  | ||||
|                         /* Determine if this is an application timer.  */ | ||||
|                         if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout) | ||||
|                         { | ||||
|  | ||||
|                             /* Derive the application timer pointer.  */ | ||||
|  | ||||
|                             /* Pickup the application timer pointer.  */ | ||||
|                             TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr) | ||||
|  | ||||
|                             /* Increment the number of expiration adjustments on this timer.  */ | ||||
|                             if (timer_ptr -> tx_timer_id == TX_TIMER_ID) | ||||
|                             { | ||||
|  | ||||
|                                 timer_ptr -> tx_timer_performance__expiration_adjust_count++; | ||||
|                             } | ||||
|                         } | ||||
| #endif | ||||
|  | ||||
|                         /* Decrement the remaining ticks of the timer.  */ | ||||
|                         current_timer -> tx_timer_internal_remaining_ticks = | ||||
|                                 current_timer -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES; | ||||
|  | ||||
|                         /* Set the timeout function to NULL in order to bypass the | ||||
|                            expiration.  */ | ||||
|                         timeout_function =  TX_NULL; | ||||
|  | ||||
|                         /* Make the timer appear that it is still active while interrupts | ||||
|                            are enabled.  This will permit proper processing of a timer | ||||
|                            deactivate from an ISR.  */ | ||||
|                         current_timer -> tx_timer_internal_list_head =    &reactivate_timer; | ||||
|                         current_timer -> tx_timer_internal_active_next =  current_timer; | ||||
|  | ||||
|                         /* Setup the temporary timer list head pointer.  */ | ||||
|                         reactivate_timer =  current_timer; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|  | ||||
|                         /* Timer did expire.  */ | ||||
|  | ||||
| #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                         /* Increment the total expirations counter.  */ | ||||
|                         _tx_timer_performance_expiration_count++; | ||||
|  | ||||
|                         /* Determine if this is an application timer.  */ | ||||
|                         if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout) | ||||
|                         { | ||||
|  | ||||
|                             /* Derive the application timer pointer.  */ | ||||
|  | ||||
|                             /* Pickup the application timer pointer.  */ | ||||
|                             TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr) | ||||
|  | ||||
|                             /* Increment the number of expirations on this timer.  */ | ||||
|                             if (timer_ptr -> tx_timer_id == TX_TIMER_ID) | ||||
|                             { | ||||
|  | ||||
|                                 timer_ptr -> tx_timer_performance_expiration_count++; | ||||
|                             } | ||||
|                         } | ||||
| #endif | ||||
|  | ||||
|                         /* Copy the calling function and ID into local variables before interrupts | ||||
|                            are re-enabled.  */ | ||||
|                         timeout_function =  current_timer -> tx_timer_internal_timeout_function; | ||||
|                         timeout_param =     current_timer -> tx_timer_internal_timeout_param; | ||||
|  | ||||
|                         /* Copy the reinitialize ticks into the remaining ticks.  */ | ||||
|                         current_timer -> tx_timer_internal_remaining_ticks =  current_timer -> tx_timer_internal_re_initialize_ticks; | ||||
|  | ||||
|                         /* Determine if the timer should be reactivated.  */ | ||||
|                         if (current_timer -> tx_timer_internal_remaining_ticks != ((ULONG) 0)) | ||||
|                         { | ||||
|  | ||||
|                             /* Make the timer appear that it is still active while processing | ||||
|                                the expiration routine and with interrupts enabled.  This will | ||||
|                                permit proper processing of a timer deactivate from both the | ||||
|                                expiration routine and an ISR.  */ | ||||
|                             current_timer -> tx_timer_internal_list_head =    &reactivate_timer; | ||||
|                             current_timer -> tx_timer_internal_active_next =  current_timer; | ||||
|  | ||||
|                             /* Setup the temporary timer list head pointer.  */ | ||||
|                             reactivate_timer =  current_timer; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* Set the list pointer of this timer to NULL.  This is used to indicate | ||||
|                                the timer is no longer active.  */ | ||||
|                             current_timer -> tx_timer_internal_list_head =  TX_NULL; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     /* Set pointer to indicate the expired timer that is currently being processed.  */ | ||||
|                     _tx_timer_expired_timer_ptr =  current_timer; | ||||
|  | ||||
|                     /* Restore interrupts for timer expiration call.  */ | ||||
|                     TX_RESTORE | ||||
|  | ||||
|                     /* Call the timer-expiration function, if non-NULL.  */ | ||||
|                     if (timeout_function != TX_NULL) | ||||
|                     { | ||||
|  | ||||
|                         (timeout_function) (timeout_param); | ||||
|                     } | ||||
|  | ||||
|                     /* Lockout interrupts again.  */ | ||||
|                     TX_DISABLE | ||||
|  | ||||
|                     /* Clear expired timer pointer.  */ | ||||
|                     _tx_timer_expired_timer_ptr =  TX_NULL; | ||||
|  | ||||
|                     /* Determine if the timer needs to be reactivated.  */ | ||||
|                     if (reactivate_timer == current_timer) | ||||
|                     { | ||||
|  | ||||
|                         /* Reactivate the timer.  */ | ||||
|  | ||||
| #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                         /* Determine if this timer expired.  */ | ||||
|                         if (timeout_function != TX_NULL) | ||||
|                         { | ||||
|  | ||||
|                             /* Increment the total reactivations counter.  */ | ||||
|                             _tx_timer_performance_reactivate_count++; | ||||
|  | ||||
|                             /* Determine if this is an application timer.  */ | ||||
|                             if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout) | ||||
|                             { | ||||
|  | ||||
|                                 /* Derive the application timer pointer.  */ | ||||
|  | ||||
|                                 /* Pickup the application timer pointer.  */ | ||||
|                                 TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr) | ||||
|  | ||||
|                                 /* Increment the number of expirations on this timer.  */ | ||||
|                                 if (timer_ptr -> tx_timer_id == TX_TIMER_ID) | ||||
|                                 { | ||||
|  | ||||
|                                     timer_ptr -> tx_timer_performance_reactivate_count++; | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #ifdef TX_REACTIVATE_INLINE | ||||
|  | ||||
|                         /* Calculate the amount of time remaining for the timer.  */ | ||||
|                         if (current_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES) | ||||
|                         { | ||||
|  | ||||
|                             /* Set expiration time to the maximum number of entries.  */ | ||||
|                             expiration_time =  TX_TIMER_ENTRIES - ((UINT) 1); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* Timer value fits in the timer entries.  */ | ||||
|  | ||||
|                             /* Set the expiration time.  */ | ||||
|                             expiration_time =  ((UINT) current_timer -> tx_timer_internal_remaining_ticks) - ((UINT) 1); | ||||
|                         } | ||||
|  | ||||
|                         /* At this point, we are ready to put the timer back on one of | ||||
|                            the timer lists.  */ | ||||
|  | ||||
|                         /* Calculate the proper place for the timer.  */ | ||||
|                         timer_list =  TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, expiration_time); | ||||
|                         if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(timer_list) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_end)) | ||||
|                         { | ||||
|  | ||||
|                             /* Wrap from the beginning of the list.  */ | ||||
|                             delta =  TX_TIMER_POINTER_DIF(timer_list, _tx_timer_list_end); | ||||
|                             timer_list =  TX_TIMER_POINTER_ADD(_tx_timer_list_start, delta); | ||||
|                         } | ||||
|  | ||||
|                         /* Now put the timer on this list.  */ | ||||
|                         if ((*timer_list) == TX_NULL) | ||||
|                         { | ||||
|  | ||||
|                             /* This list is NULL, just put the new timer on it.  */ | ||||
|  | ||||
|                             /* Setup the links in this timer.  */ | ||||
|                             current_timer -> tx_timer_internal_active_next =      current_timer; | ||||
|                             current_timer -> tx_timer_internal_active_previous =  current_timer; | ||||
|  | ||||
|                             /* Setup the list head pointer.  */ | ||||
|                             *timer_list =  current_timer; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|  | ||||
|                             /* This list is not NULL, add current timer to the end. */ | ||||
|                             next_timer =                                          *timer_list; | ||||
|                             previous_timer =                                      next_timer -> tx_timer_internal_active_previous; | ||||
|                             previous_timer -> tx_timer_internal_active_next =     current_timer; | ||||
|                             next_timer -> tx_timer_internal_active_previous =     current_timer; | ||||
|                             current_timer -> tx_timer_internal_active_next =      next_timer; | ||||
|                             current_timer -> tx_timer_internal_active_previous =  previous_timer; | ||||
|                         } | ||||
|  | ||||
|                         /* Setup list head pointer.  */ | ||||
|                         current_timer -> tx_timer_internal_list_head =  timer_list; | ||||
| #else | ||||
|  | ||||
|                         /* Reactivate through the timer activate function.  */ | ||||
|  | ||||
|                         /* Clear the list head for the timer activate call.  */ | ||||
|                         current_timer -> tx_timer_internal_list_head = TX_NULL; | ||||
|  | ||||
|                         /* Activate the current timer.  */ | ||||
|                         _tx_timer_system_activate(current_timer); | ||||
| #endif | ||||
|                     } | ||||
|                 } | ||||
|             } while (_tx_timer_expired != TX_FALSE); | ||||
|  | ||||
|             /* Clear the timer interrupt processing active flag.  */ | ||||
|             _tx_timer_processing_active =  TX_FALSE; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
| #endif | ||||
| } | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										250
									
								
								Middlewares/ST/threadx/common/src/tx_timer_info_get.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								Middlewares/ST/threadx/common/src/tx_timer_info_get.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,250 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Timer                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_trace.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_info_get                                  PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function retrieves information from the specified timer.       */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    timer_ptr                         Pointer to timer control block    */ | ||||
| /*    name                              Destination for the timer name    */ | ||||
| /*    active                            Destination for active flag       */ | ||||
| /*    remaining_ticks                   Destination for remaining ticks   */ | ||||
| /*                                        before expiration               */ | ||||
| /*    reschedule_ticks                  Destination for reschedule ticks  */ | ||||
| /*    next_timer                        Destination for next timer on the */ | ||||
| /*                                        created list                    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _tx_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks, | ||||
|                 ULONG *reschedule_ticks, TX_TIMER **next_timer) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_TIMER_INTERNAL   *internal_ptr; | ||||
| TX_TIMER_INTERNAL   **list_head; | ||||
| ULONG               ticks_left; | ||||
| UINT                timer_active; | ||||
| UINT                active_timer_list; | ||||
|  | ||||
|  | ||||
|     /* Disable interrupts.  */ | ||||
|     TX_DISABLE | ||||
|  | ||||
|     /* If trace is enabled, insert this event into the trace buffer.  */ | ||||
|     TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_INFO_GET, timer_ptr, TX_POINTER_TO_ULONG_CONVERT(&ticks_left), 0, 0, TX_TRACE_TIMER_EVENTS) | ||||
|  | ||||
|     /* Log this kernel call.  */ | ||||
|     TX_EL_TIMER_INFO_GET_INSERT | ||||
|  | ||||
|     /* Retrieve the name of the timer.  */ | ||||
|     if (name != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *name =  timer_ptr -> tx_timer_name; | ||||
|     } | ||||
|  | ||||
|     /* Pickup address of internal timer structure.  */ | ||||
|     internal_ptr =  &(timer_ptr -> tx_timer_internal); | ||||
|  | ||||
|     /* Retrieve all the pertinent information and return it in the supplied | ||||
|        destinations.  */ | ||||
|  | ||||
|     /* Default active to false.  */ | ||||
|     timer_active =  TX_FALSE; | ||||
|  | ||||
|     /* Default the ticks left to the remaining ticks.  */ | ||||
|     ticks_left =  internal_ptr -> tx_timer_internal_remaining_ticks; | ||||
|  | ||||
|     /* Determine if the timer is still active.  */ | ||||
|     if (internal_ptr -> tx_timer_internal_list_head != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Indicate this timer is active.  */ | ||||
|         timer_active =  TX_TRUE; | ||||
|  | ||||
|         /* Default the active timer list flag to false.  */ | ||||
|         active_timer_list =  TX_FALSE; | ||||
|  | ||||
|         /* Determine if the timer is still active.  */ | ||||
|         if (internal_ptr -> tx_timer_internal_list_head >= _tx_timer_list_start) | ||||
|         { | ||||
|  | ||||
|             /* Determine if the list head is before the end of the list.  */ | ||||
|             if (internal_ptr -> tx_timer_internal_list_head < _tx_timer_list_end) | ||||
|             { | ||||
|  | ||||
|                 /* This timer is active and has not yet expired.  */ | ||||
|                 active_timer_list =  TX_TRUE; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Determine if the timer is on the active timer list.  */ | ||||
|         if (active_timer_list == TX_TRUE) | ||||
|         { | ||||
|  | ||||
|             /* Calculate the amount of time that has elapsed since the timer | ||||
|                was activated.  */ | ||||
|  | ||||
|             /* Setup the list head pointer.  */ | ||||
|             list_head =  internal_ptr -> tx_timer_internal_list_head; | ||||
|  | ||||
|             /* Is this timer's entry after the current timer pointer?  */ | ||||
|             if (internal_ptr -> tx_timer_internal_list_head >= _tx_timer_current_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Calculate ticks left to expiration - just the difference between this | ||||
|                    timer's entry and the current timer pointer.  */ | ||||
|                 ticks_left =  ((TX_TIMER_POINTER_DIF(list_head, _tx_timer_current_ptr)) + ((ULONG) 1)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Calculate the ticks left with a wrapped list condition.  */ | ||||
|                 ticks_left =  ((TX_TIMER_POINTER_DIF(list_head, _tx_timer_list_start))); | ||||
|  | ||||
|                 ticks_left =  ticks_left + ((TX_TIMER_POINTER_DIF(_tx_timer_list_end, _tx_timer_current_ptr)) + ((ULONG) 1)); | ||||
|             } | ||||
|  | ||||
|             /* Adjust the remaining ticks accordingly.  */ | ||||
|             if (internal_ptr -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES) | ||||
|             { | ||||
|  | ||||
|                 /* Subtract off the last full pass through the timer list and add the | ||||
|                    time left.  */ | ||||
|                 ticks_left =  (internal_ptr -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES) + ticks_left; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* The timer is not on the actual timer list so it must either be being processed | ||||
|                or on a temporary list to be processed.   */ | ||||
|  | ||||
|             /* Check to see if this timer is the timer currently being processed.  */ | ||||
|             if (_tx_timer_expired_timer_ptr == internal_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Timer dispatch routine is executing, waiting to execute, or just finishing. No more remaining ticks for this expiration.  */ | ||||
|                 ticks_left =  ((ULONG) 0); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Timer is not the one being processed, which means it must be on the temporary expiration list | ||||
|                    waiting to be processed.  */ | ||||
|  | ||||
|                 /* Calculate the remaining ticks for a timer in the process of expiring.  */ | ||||
|                 if (ticks_left > TX_TIMER_ENTRIES) | ||||
|                 { | ||||
|  | ||||
|                     /* Calculate the number of ticks remaining.  */ | ||||
|                     ticks_left =  internal_ptr -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* Timer dispatch routine is waiting to execute, no more remaining ticks for this expiration.  */ | ||||
|                     ticks_left =  ((ULONG) 0); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Setup return values for an inactive timer.  */ | ||||
|     if (active != TX_NULL) | ||||
|     { | ||||
|  | ||||
|        /* Setup the timer active indication.  */ | ||||
|        *active =  timer_active; | ||||
|     } | ||||
|     if (remaining_ticks != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Setup the default remaining ticks value.  */ | ||||
|         *remaining_ticks =  ticks_left; | ||||
|     } | ||||
|  | ||||
|     /* Pickup the reschedule ticks value.  */ | ||||
|     if (reschedule_ticks != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *reschedule_ticks =  internal_ptr -> tx_timer_internal_re_initialize_ticks; | ||||
|     } | ||||
|  | ||||
|     /* Pickup the next created application timer.  */ | ||||
|     if (next_timer != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         *next_timer =  timer_ptr -> tx_timer_created_next; | ||||
|     } | ||||
|  | ||||
|     /* Restore interrupts.  */ | ||||
|     TX_RESTORE | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(TX_SUCCESS); | ||||
| } | ||||
|  | ||||
							
								
								
									
										306
									
								
								Middlewares/ST/threadx/common/src/tx_timer_initialize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										306
									
								
								Middlewares/ST/threadx/common/src/tx_timer_initialize.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,306 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Timer                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
|  | ||||
| /* Check for the TX_NO_TIMER option. When defined, do not define all of the | ||||
|    timer component global variables.  */ | ||||
|  | ||||
| #ifndef TX_NO_TIMER | ||||
|  | ||||
|  | ||||
| /* Define the system clock value that is continually incremented by the | ||||
|    periodic timer interrupt processing.  */ | ||||
|  | ||||
| volatile ULONG      _tx_timer_system_clock; | ||||
|  | ||||
|  | ||||
| /* Define the time-slice expiration flag.  This is used to indicate that a time-slice | ||||
|    has happened.  */ | ||||
|  | ||||
| UINT                _tx_timer_expired_time_slice; | ||||
|  | ||||
|  | ||||
| /* Define the thread and application timer entry list.  This list provides a direct access | ||||
|    method for insertion of times less than TX_TIMER_ENTRIES.  */ | ||||
|  | ||||
| TX_TIMER_INTERNAL   *_tx_timer_list[TX_TIMER_ENTRIES]; | ||||
|  | ||||
|  | ||||
| /* Define the boundary pointers to the list.  These are setup to easily manage | ||||
|    wrapping the list.  */ | ||||
|  | ||||
| TX_TIMER_INTERNAL   **_tx_timer_list_start; | ||||
| TX_TIMER_INTERNAL   **_tx_timer_list_end; | ||||
|  | ||||
|  | ||||
| /* Define the current timer pointer in the list.  This pointer is moved sequentially | ||||
|    through the timer list by the timer interrupt handler.  */ | ||||
|  | ||||
| TX_TIMER_INTERNAL   **_tx_timer_current_ptr; | ||||
|  | ||||
|  | ||||
| /* Define the timer expiration flag.  This is used to indicate that a timer | ||||
|    has expired.  */ | ||||
|  | ||||
| UINT                _tx_timer_expired; | ||||
|  | ||||
|  | ||||
| /* Define the created timer list head pointer.  */ | ||||
|  | ||||
| TX_TIMER            *_tx_timer_created_ptr; | ||||
|  | ||||
|  | ||||
| /* Define the created timer count.  */ | ||||
|  | ||||
| ULONG               _tx_timer_created_count; | ||||
|  | ||||
|  | ||||
| /* Define the pointer to the timer that has expired and is being processed.  */ | ||||
|  | ||||
| TX_TIMER_INTERNAL  *_tx_timer_expired_timer_ptr; | ||||
|  | ||||
|  | ||||
| #ifndef TX_TIMER_PROCESS_IN_ISR | ||||
|  | ||||
| /* Define the timer thread's control block.  */ | ||||
|  | ||||
| TX_THREAD           _tx_timer_thread; | ||||
|  | ||||
|  | ||||
| /* Define the variable that holds the timer thread's starting stack address.  */ | ||||
|  | ||||
| VOID                *_tx_timer_stack_start; | ||||
|  | ||||
|  | ||||
| /* Define the variable that holds the timer thread's stack size.  */ | ||||
|  | ||||
| ULONG               _tx_timer_stack_size; | ||||
|  | ||||
|  | ||||
| /* Define the variable that holds the timer thread's priority.  */ | ||||
|  | ||||
| UINT                _tx_timer_priority; | ||||
|  | ||||
| /* Define the system timer thread's stack.   The default size is defined | ||||
|    in tx_port.h.  */ | ||||
|  | ||||
| ULONG               _tx_timer_thread_stack_area[(((UINT) TX_TIMER_THREAD_STACK_SIZE)+((sizeof(ULONG))- ((UINT) 1)))/(sizeof(ULONG))]; | ||||
|  | ||||
| #else | ||||
|  | ||||
|  | ||||
| /* Define the busy flag that will prevent nested timer ISR processing.  */ | ||||
|  | ||||
| UINT                _tx_timer_processing_active; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
| /* Define the total number of timer activations.  */ | ||||
|  | ||||
| ULONG               _tx_timer_performance_activate_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of timer reactivations.  */ | ||||
|  | ||||
| ULONG               _tx_timer_performance_reactivate_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of timer deactivations.  */ | ||||
|  | ||||
| ULONG               _tx_timer_performance_deactivate_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of timer expirations.  */ | ||||
|  | ||||
| ULONG               _tx_timer_performance_expiration_count; | ||||
|  | ||||
|  | ||||
| /* Define the total number of timer expiration adjustments. These are required | ||||
|    if the expiration time is greater than the size of the timer list. In such | ||||
|    cases, the timer is placed at the end of the list and then reactivated | ||||
|    as many times as necessary to finally achieve the resulting timeout. */ | ||||
|  | ||||
| ULONG               _tx_timer_performance__expiration_adjust_count; | ||||
|  | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /* Define the current time slice value.  If non-zero, a time-slice is active. | ||||
|    Otherwise, the time_slice is not active.  */ | ||||
|  | ||||
| ULONG               _tx_timer_time_slice; | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_initialize                                PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function initializes the various control data structures for   */ | ||||
| /*    the clock control component.                                        */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_create                 Create the system timer thread    */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_initialize_high_level         High level initialization         */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_timer_initialize(VOID) | ||||
| { | ||||
| #ifndef TX_NO_TIMER | ||||
| #ifndef TX_TIMER_PROCESS_IN_ISR | ||||
| UINT    status; | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_DISABLE_REDUNDANT_CLEARING | ||||
|  | ||||
|     /* Initialize the system clock to 0.  */ | ||||
|     _tx_timer_system_clock =  ((ULONG) 0); | ||||
|  | ||||
|     /* Initialize the time-slice value to 0 to make sure it is disabled.  */ | ||||
|     _tx_timer_time_slice =  ((ULONG) 0); | ||||
|  | ||||
|     /* Clear the expired flags.  */ | ||||
|     _tx_timer_expired_time_slice =  TX_FALSE; | ||||
|     _tx_timer_expired =             TX_FALSE; | ||||
|  | ||||
|     /* Set the currently expired timer being processed pointer to NULL.  */ | ||||
|     _tx_timer_expired_timer_ptr =  TX_NULL; | ||||
|  | ||||
|     /* Initialize the thread and application timer management control structures.  */ | ||||
|  | ||||
|     /* First, initialize the timer list.  */ | ||||
|     TX_MEMSET(&_tx_timer_list[0], 0, (sizeof(_tx_timer_list))); | ||||
| #endif | ||||
|  | ||||
|     /* Initialize all of the list pointers.  */ | ||||
|     _tx_timer_list_start =   &_tx_timer_list[0]; | ||||
|     _tx_timer_current_ptr =  &_tx_timer_list[0]; | ||||
|  | ||||
|     /* Set the timer list end pointer to one past the actual timer list.  This is done | ||||
|        to make the timer interrupt handling in assembly language a little easier.  */ | ||||
|     _tx_timer_list_end =     &_tx_timer_list[TX_TIMER_ENTRIES-((ULONG) 1)]; | ||||
|     _tx_timer_list_end =     TX_TIMER_POINTER_ADD(_tx_timer_list_end, ((ULONG) 1)); | ||||
|  | ||||
| #ifndef TX_TIMER_PROCESS_IN_ISR | ||||
|  | ||||
|     /* Setup the variables associated with the system timer thread's stack and | ||||
|        priority.  */ | ||||
|     _tx_timer_stack_start =  (VOID *) &_tx_timer_thread_stack_area[0]; | ||||
|     _tx_timer_stack_size =   ((ULONG) TX_TIMER_THREAD_STACK_SIZE); | ||||
|     _tx_timer_priority =     ((UINT) TX_TIMER_THREAD_PRIORITY); | ||||
|  | ||||
|     /* Create the system timer thread.  This thread processes all of the timer | ||||
|        expirations and reschedules.  Its stack and priority are defined in the | ||||
|        low-level initialization component.  */ | ||||
|     do | ||||
|     { | ||||
|  | ||||
|         /* Create the system timer thread.  */ | ||||
|         status =  _tx_thread_create(&_tx_timer_thread, | ||||
|                                     TX_CONST_CHAR_TO_CHAR_POINTER_CONVERT("System Timer Thread"), | ||||
|                                     _tx_timer_thread_entry, | ||||
|                                     ((ULONG) TX_TIMER_ID), | ||||
|                                     _tx_timer_stack_start, _tx_timer_stack_size, | ||||
|                                     _tx_timer_priority, _tx_timer_priority, TX_NO_TIME_SLICE, TX_DONT_START); | ||||
|  | ||||
| #ifdef TX_SAFETY_CRITICAL | ||||
|  | ||||
|         /* Check return from thread create - if an error is detected throw an exception.  */ | ||||
|         if (status != TX_SUCCESS) | ||||
|         { | ||||
|  | ||||
|             /* Raise safety critical exception.  */ | ||||
|             TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, status); | ||||
|         } | ||||
| #endif | ||||
|  | ||||
|         /* Define timer initialize extension.  */ | ||||
|         TX_TIMER_INITIALIZE_EXTENSION(status) | ||||
|  | ||||
|     } while (status != TX_SUCCESS); | ||||
|  | ||||
| #else | ||||
|  | ||||
|     /* Clear the timer interrupt processing active flag.  */ | ||||
|     _tx_timer_processing_active =  TX_FALSE; | ||||
| #endif | ||||
|  | ||||
| #ifndef TX_DISABLE_REDUNDANT_CLEARING | ||||
|  | ||||
|     /* Initialize the head pointer of the created application timer list.  */ | ||||
|     _tx_timer_created_ptr =  TX_NULL; | ||||
|  | ||||
|     /* Set the created count to zero.  */ | ||||
|     _tx_timer_created_count =  TX_EMPTY; | ||||
|  | ||||
| #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|     /* Initialize timer performance counters.  */ | ||||
|     _tx_timer_performance_activate_count =           ((ULONG) 0); | ||||
|     _tx_timer_performance_reactivate_count =         ((ULONG) 0); | ||||
|     _tx_timer_performance_deactivate_count =         ((ULONG) 0); | ||||
|     _tx_timer_performance_expiration_count =         ((ULONG) 0); | ||||
|     _tx_timer_performance__expiration_adjust_count =  ((ULONG) 0); | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										170
									
								
								Middlewares/ST/threadx/common/src/tx_timer_system_activate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								Middlewares/ST/threadx/common/src/tx_timer_system_activate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Timer                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
| #ifndef TX_NO_TIMER | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_system_activate                           PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function places the specified internal timer in the proper     */ | ||||
| /*    place in the timer expiration list.  If the timer is already active */ | ||||
| /*    this function does nothing.                                         */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    timer_ptr                         Pointer to timer control block    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Always returns success            */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_suspend         Thread suspend function           */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*    _tx_timer_thread_entry            Timer thread processing           */ | ||||
| /*    _tx_timer_activate                Application timer activate        */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Scott Larson             Modified comment(s), and      */ | ||||
| /*                                            opt out of function when    */ | ||||
| /*                                            TX_NO_TIMER is defined,     */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_timer_system_activate(TX_TIMER_INTERNAL *timer_ptr) | ||||
| { | ||||
|  | ||||
| TX_TIMER_INTERNAL           **timer_list; | ||||
| TX_TIMER_INTERNAL           *next_timer; | ||||
| TX_TIMER_INTERNAL           *previous_timer; | ||||
| ULONG                       delta; | ||||
| ULONG                       remaining_ticks; | ||||
| ULONG                       expiration_time; | ||||
|  | ||||
|  | ||||
|     /* Pickup the remaining ticks.  */ | ||||
|     remaining_ticks =  timer_ptr -> tx_timer_internal_remaining_ticks; | ||||
|  | ||||
|     /* Determine if there is a timer to activate.  */ | ||||
|     if (remaining_ticks != ((ULONG) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Determine if the timer is set to wait forever.  */ | ||||
|         if (remaining_ticks != TX_WAIT_FOREVER) | ||||
|         { | ||||
|  | ||||
|             /* Valid timer activate request.  */ | ||||
|  | ||||
|             /* Determine if the timer still needs activation.  */ | ||||
|             if (timer_ptr -> tx_timer_internal_list_head == TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Activate the timer.  */ | ||||
|  | ||||
|                 /* Calculate the amount of time remaining for the timer.  */ | ||||
|                 if (remaining_ticks > TX_TIMER_ENTRIES) | ||||
|                 { | ||||
|  | ||||
|                     /* Set expiration time to the maximum number of entries.  */ | ||||
|                     expiration_time =  TX_TIMER_ENTRIES - ((ULONG) 1); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* Timer value fits in the timer entries.  */ | ||||
|  | ||||
|                     /* Set the expiration time.  */ | ||||
|                     expiration_time =  (remaining_ticks - ((ULONG) 1)); | ||||
|                 } | ||||
|  | ||||
|                 /* At this point, we are ready to put the timer on one of | ||||
|                    the timer lists.  */ | ||||
|  | ||||
|                 /* Calculate the proper place for the timer.  */ | ||||
|                 timer_list =  TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, expiration_time); | ||||
|                 if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(timer_list) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_end)) | ||||
|                 { | ||||
|  | ||||
|                     /* Wrap from the beginning of the list.  */ | ||||
|                     delta =  TX_TIMER_POINTER_DIF(timer_list, _tx_timer_list_end); | ||||
|                     timer_list =  TX_TIMER_POINTER_ADD(_tx_timer_list_start, delta); | ||||
|                 } | ||||
|  | ||||
|                 /* Now put the timer on this list.  */ | ||||
|                 if ((*timer_list) == TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     /* This list is NULL, just put the new timer on it.  */ | ||||
|  | ||||
|                     /* Setup the links in this timer.  */ | ||||
|                     timer_ptr -> tx_timer_internal_active_next =      timer_ptr; | ||||
|                     timer_ptr -> tx_timer_internal_active_previous =  timer_ptr; | ||||
|  | ||||
|                     /* Setup the list head pointer.  */ | ||||
|                     *timer_list =  timer_ptr; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* This list is not NULL, add current timer to the end. */ | ||||
|                     next_timer =                                        *timer_list; | ||||
|                     previous_timer =                                    next_timer -> tx_timer_internal_active_previous; | ||||
|                     previous_timer -> tx_timer_internal_active_next =   timer_ptr; | ||||
|                     next_timer -> tx_timer_internal_active_previous =   timer_ptr; | ||||
|                     timer_ptr -> tx_timer_internal_active_next =        next_timer; | ||||
|                     timer_ptr -> tx_timer_internal_active_previous =    previous_timer; | ||||
|                 } | ||||
|  | ||||
|                 /* Setup list head pointer.  */ | ||||
|                 timer_ptr -> tx_timer_internal_list_head =  timer_list; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										134
									
								
								Middlewares/ST/threadx/common/src/tx_timer_system_deactivate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								Middlewares/ST/threadx/common/src/tx_timer_system_deactivate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Timer                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_timer.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_system_deactivate                         PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function deactivates, or removes the timer from the active     */ | ||||
| /*    timer expiration list.  If the timer is already deactivated, this   */ | ||||
| /*    function just returns.                                              */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    timer_ptr                         Pointer to timer control block    */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_SUCCESS                        Always returns success            */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_thread_system_resume          Thread resume function            */ | ||||
| /*    _tx_timer_thread_entry            Timer thread processing           */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| VOID  _tx_timer_system_deactivate(TX_TIMER_INTERNAL *timer_ptr) | ||||
| { | ||||
|  | ||||
| TX_TIMER_INTERNAL   **list_head; | ||||
| TX_TIMER_INTERNAL   *next_timer; | ||||
| TX_TIMER_INTERNAL   *previous_timer; | ||||
|  | ||||
|  | ||||
|     /* Pickup the list head pointer.  */ | ||||
|     list_head =  timer_ptr -> tx_timer_internal_list_head; | ||||
|  | ||||
|     /* Determine if the timer still needs deactivation.  */ | ||||
|     if (list_head != TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Deactivate the timer.  */ | ||||
|  | ||||
|         /* Pickup the next active timer.  */ | ||||
|         next_timer =  timer_ptr -> tx_timer_internal_active_next; | ||||
|  | ||||
|         /* See if this is the only timer in the list.  */ | ||||
|         if (timer_ptr == next_timer) | ||||
|         { | ||||
|  | ||||
|             /* Yes, the only timer on the list.  */ | ||||
|  | ||||
|             /* Determine if the head pointer needs to be updated.  */ | ||||
|             if (*(list_head) == timer_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Update the head pointer.  */ | ||||
|                 *(list_head) =  TX_NULL; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* At least one more timer is on the same expiration list.  */ | ||||
|  | ||||
|             /* Update the links of the adjacent timers.  */ | ||||
|             previous_timer =                                   timer_ptr -> tx_timer_internal_active_previous; | ||||
|             next_timer -> tx_timer_internal_active_previous =  previous_timer; | ||||
|             previous_timer -> tx_timer_internal_active_next =  next_timer; | ||||
|  | ||||
|             /* Determine if the head pointer needs to be updated.  */ | ||||
|             if (*(list_head) == timer_ptr) | ||||
|             { | ||||
|  | ||||
|                 /* Update the next timer in the list with the list head pointer.  */ | ||||
|                 next_timer -> tx_timer_internal_list_head =  list_head; | ||||
|  | ||||
|                 /* Update the head pointer.  */ | ||||
|                 *(list_head) =  next_timer; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Clear the timer's list head pointer.  */ | ||||
|         timer_ptr -> tx_timer_internal_list_head =  TX_NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										482
									
								
								Middlewares/ST/threadx/common/src/tx_timer_thread_entry.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										482
									
								
								Middlewares/ST/threadx/common/src/tx_timer_thread_entry.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,482 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Timer                                                               */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_timer.h" | ||||
| #include "tx_thread.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_timer_thread_entry                              PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function manages thread and application timer expirations.     */ | ||||
| /*    Actually, from this thread's point of view, there is no difference. */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    timer_thread_input                Used just for verification        */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    None                                                                */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    Timer Expiration Function                                           */ | ||||
| /*    _tx_thread_system_suspend         Thread suspension                 */ | ||||
| /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */ | ||||
| /*    _tx_timer_system_activate         Timer reactivate processing       */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    ThreadX Scheduler                                                   */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| #ifndef TX_TIMER_PROCESS_IN_ISR | ||||
| VOID  _tx_timer_thread_entry(ULONG timer_thread_input) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| TX_TIMER_INTERNAL           *expired_timers; | ||||
| TX_TIMER_INTERNAL           *reactivate_timer; | ||||
| TX_TIMER_INTERNAL           *next_timer; | ||||
| TX_TIMER_INTERNAL           *previous_timer; | ||||
| TX_TIMER_INTERNAL           *current_timer; | ||||
| VOID                        (*timeout_function)(ULONG id); | ||||
| ULONG                       timeout_param =  ((ULONG) 0); | ||||
| TX_THREAD                   *thread_ptr; | ||||
| #ifdef TX_REACTIVATE_INLINE | ||||
| TX_TIMER_INTERNAL           **timer_list;               /* Timer list pointer           */ | ||||
| UINT                        expiration_time;            /* Value used for pointer offset*/ | ||||
| ULONG                       delta; | ||||
| #endif | ||||
| #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO | ||||
| TX_TIMER                    *timer_ptr; | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     /* Make sure the timer input is correct.  This also gets rid of the | ||||
|        silly compiler warnings.  */ | ||||
|     if (timer_thread_input == TX_TIMER_ID) | ||||
|     { | ||||
|  | ||||
|         /* Yes, valid thread entry, proceed...  */ | ||||
|  | ||||
|         /* Now go into an infinite loop to process timer expirations.  */ | ||||
|         while (TX_LOOP_FOREVER) | ||||
|         { | ||||
|  | ||||
|             /* First, move the current list pointer and clear the timer | ||||
|                expired value.  This allows the interrupt handling portion | ||||
|                to continue looking for timer expirations.  */ | ||||
|             TX_DISABLE | ||||
|  | ||||
|             /* Save the current timer expiration list pointer.  */ | ||||
|             expired_timers =  *_tx_timer_current_ptr; | ||||
|  | ||||
|             /* Modify the head pointer in the first timer in the list, if there | ||||
|                is one!  */ | ||||
|             if (expired_timers != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 expired_timers -> tx_timer_internal_list_head =  &expired_timers; | ||||
|             } | ||||
|  | ||||
|             /* Set the current list pointer to NULL.  */ | ||||
|             *_tx_timer_current_ptr =  TX_NULL; | ||||
|  | ||||
|             /* Move the current pointer up one timer entry wrap if we get to | ||||
|                the end of the list.  */ | ||||
|             _tx_timer_current_ptr =  TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, 1); | ||||
|             if (_tx_timer_current_ptr == _tx_timer_list_end) | ||||
|             { | ||||
|  | ||||
|                 _tx_timer_current_ptr =  _tx_timer_list_start; | ||||
|             } | ||||
|  | ||||
|             /* Clear the expired flag.  */ | ||||
|             _tx_timer_expired =  TX_FALSE; | ||||
|  | ||||
|             /* Restore interrupts temporarily.  */ | ||||
|             TX_RESTORE | ||||
|  | ||||
|             /* Disable interrupts again.  */ | ||||
|             TX_DISABLE | ||||
|  | ||||
|             /* Next, process the expiration of the associated timers at this | ||||
|                time slot.  */ | ||||
|             while (expired_timers != TX_NULL) | ||||
|             { | ||||
|  | ||||
|                 /* Something is on the list.  Remove it and process the expiration.  */ | ||||
|                 current_timer =  expired_timers; | ||||
|  | ||||
|                 /* Pickup the next timer.  */ | ||||
|                 next_timer =  expired_timers -> tx_timer_internal_active_next; | ||||
|  | ||||
|                 /* Set the reactivate_timer to NULL.  */ | ||||
|                 reactivate_timer =  TX_NULL; | ||||
|  | ||||
|                 /* Determine if this is the only timer.  */ | ||||
|                 if (current_timer == next_timer) | ||||
|                 { | ||||
|  | ||||
|                     /* Yes, this is the only timer in the list.  */ | ||||
|  | ||||
|                     /* Set the head pointer to NULL.  */ | ||||
|                     expired_timers =  TX_NULL; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* No, not the only expired timer.  */ | ||||
|  | ||||
|                     /* Remove this timer from the expired list.  */ | ||||
|                     previous_timer =                                   current_timer -> tx_timer_internal_active_previous; | ||||
|                     next_timer -> tx_timer_internal_active_previous =  previous_timer; | ||||
|                     previous_timer -> tx_timer_internal_active_next =  next_timer; | ||||
|  | ||||
|                     /* Modify the next timer's list head to point at the current list head.  */ | ||||
|                     next_timer -> tx_timer_internal_list_head =  &expired_timers; | ||||
|  | ||||
|                     /* Set the list head pointer.  */ | ||||
|                     expired_timers =  next_timer; | ||||
|                 } | ||||
|  | ||||
|                 /* In any case, the timer is now off of the expired list.  */ | ||||
|  | ||||
|                 /* Determine if the timer has expired or if it is just a really | ||||
|                    big timer that needs to be placed in the list again.  */ | ||||
|                 if (current_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES) | ||||
|                 { | ||||
|  | ||||
|                     /* Timer is bigger than the timer entries and must be | ||||
|                        rescheduled.  */ | ||||
|  | ||||
| #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                     /* Increment the total expiration adjustments counter.  */ | ||||
|                     _tx_timer_performance__expiration_adjust_count++; | ||||
|  | ||||
|                     /* Determine if this is an application timer.  */ | ||||
|                     if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout) | ||||
|                     { | ||||
|  | ||||
|                         /* Derive the application timer pointer.  */ | ||||
|  | ||||
|                         /* Pickup the application timer pointer.  */ | ||||
|                         TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr) | ||||
|  | ||||
|                         /* Increment the number of expiration adjustments on this timer.  */ | ||||
|                         if (timer_ptr -> tx_timer_id == TX_TIMER_ID) | ||||
|                         { | ||||
|  | ||||
|                             timer_ptr -> tx_timer_performance__expiration_adjust_count++; | ||||
|                         } | ||||
|                     } | ||||
| #endif | ||||
|  | ||||
|                     /* Decrement the remaining ticks of the timer.  */ | ||||
|                     current_timer -> tx_timer_internal_remaining_ticks = | ||||
|                             current_timer -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES; | ||||
|  | ||||
|                     /* Set the timeout function to NULL in order to bypass the | ||||
|                        expiration.  */ | ||||
|                     timeout_function =  TX_NULL; | ||||
|  | ||||
|                     /* Make the timer appear that it is still active while interrupts | ||||
|                        are enabled.  This will permit proper processing of a timer | ||||
|                        deactivate from an ISR.  */ | ||||
|                     current_timer -> tx_timer_internal_list_head =    &reactivate_timer; | ||||
|                     current_timer -> tx_timer_internal_active_next =  current_timer; | ||||
|  | ||||
|                     /* Setup the temporary timer list head pointer.  */ | ||||
|                     reactivate_timer =  current_timer; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
|                     /* Timer did expire.  */ | ||||
|  | ||||
| #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                     /* Increment the total expirations counter.  */ | ||||
|                     _tx_timer_performance_expiration_count++; | ||||
|  | ||||
|                     /* Determine if this is an application timer.  */ | ||||
|                     if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout) | ||||
|                     { | ||||
|  | ||||
|                         /* Derive the application timer pointer.  */ | ||||
|  | ||||
|                         /* Pickup the application timer pointer.  */ | ||||
|                         TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr) | ||||
|  | ||||
|                         /* Increment the number of expirations on this timer.  */ | ||||
|                         if (timer_ptr -> tx_timer_id == TX_TIMER_ID) | ||||
|                         { | ||||
|  | ||||
|                             timer_ptr -> tx_timer_performance_expiration_count++; | ||||
|                         } | ||||
|                     } | ||||
| #endif | ||||
|  | ||||
|                     /* Copy the calling function and ID into local variables before interrupts | ||||
|                        are re-enabled.  */ | ||||
|                     timeout_function =  current_timer -> tx_timer_internal_timeout_function; | ||||
|                     timeout_param =     current_timer -> tx_timer_internal_timeout_param; | ||||
|  | ||||
|                     /* Copy the reinitialize ticks into the remaining ticks.  */ | ||||
|                     current_timer -> tx_timer_internal_remaining_ticks =  current_timer -> tx_timer_internal_re_initialize_ticks; | ||||
|  | ||||
|                     /* Determine if the timer should be reactivated.  */ | ||||
|                     if (current_timer -> tx_timer_internal_remaining_ticks != ((ULONG) 0)) | ||||
|                     { | ||||
|  | ||||
|                         /* Make the timer appear that it is still active while processing | ||||
|                            the expiration routine and with interrupts enabled.  This will | ||||
|                            permit proper processing of a timer deactivate from both the | ||||
|                            expiration routine and an ISR.  */ | ||||
|                         current_timer -> tx_timer_internal_list_head =    &reactivate_timer; | ||||
|                         current_timer -> tx_timer_internal_active_next =  current_timer; | ||||
|  | ||||
|                         /* Setup the temporary timer list head pointer.  */ | ||||
|                         reactivate_timer =  current_timer; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|  | ||||
|                         /* Set the list pointer of this timer to NULL.  This is used to indicate | ||||
|                            the timer is no longer active.  */ | ||||
|                         current_timer -> tx_timer_internal_list_head =  TX_NULL; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 /* Set pointer to indicate the expired timer that is currently being processed.  */ | ||||
|                 _tx_timer_expired_timer_ptr =  current_timer; | ||||
|  | ||||
|                 /* Restore interrupts for timer expiration call.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Call the timer-expiration function, if non-NULL.  */ | ||||
|                 if (timeout_function != TX_NULL) | ||||
|                 { | ||||
|  | ||||
|                     (timeout_function) (timeout_param); | ||||
|                 } | ||||
|  | ||||
|                 /* Lockout interrupts again.  */ | ||||
|                 TX_DISABLE | ||||
|  | ||||
|                 /* Clear expired timer pointer.  */ | ||||
|                 _tx_timer_expired_timer_ptr =  TX_NULL; | ||||
|  | ||||
|                 /* Determine if the timer needs to be reactivated.  */ | ||||
|                 if (reactivate_timer == current_timer) | ||||
|                 { | ||||
|  | ||||
|                     /* Reactivate the timer.  */ | ||||
|  | ||||
| #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO | ||||
|  | ||||
|                     /* Determine if this timer expired.  */ | ||||
|                     if (timeout_function != TX_NULL) | ||||
|                     { | ||||
|  | ||||
|                         /* Increment the total reactivations counter.  */ | ||||
|                         _tx_timer_performance_reactivate_count++; | ||||
|  | ||||
|                         /* Determine if this is an application timer.  */ | ||||
|                         if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout) | ||||
|                         { | ||||
|  | ||||
|                             /* Derive the application timer pointer.  */ | ||||
|  | ||||
|                             /* Pickup the application timer pointer.  */ | ||||
|                             TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr) | ||||
|  | ||||
|                             /* Increment the number of expirations on this timer.  */ | ||||
|                             if (timer_ptr -> tx_timer_id == TX_TIMER_ID) | ||||
|                             { | ||||
|  | ||||
|                                 timer_ptr -> tx_timer_performance_reactivate_count++; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
| #endif | ||||
|  | ||||
| #ifdef TX_REACTIVATE_INLINE | ||||
|  | ||||
|                     /* Calculate the amount of time remaining for the timer.  */ | ||||
|                     if (current_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES) | ||||
|                     { | ||||
|  | ||||
|                         /* Set expiration time to the maximum number of entries.  */ | ||||
|                         expiration_time =  TX_TIMER_ENTRIES - ((UINT) 1); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|  | ||||
|                         /* Timer value fits in the timer entries.  */ | ||||
|  | ||||
|                         /* Set the expiration time.  */ | ||||
|                         expiration_time =  ((UINT) current_timer -> tx_timer_internal_remaining_ticks) - ((UINT) 1); | ||||
|                     } | ||||
|  | ||||
|                     /* At this point, we are ready to put the timer back on one of | ||||
|                        the timer lists.  */ | ||||
|  | ||||
|                     /* Calculate the proper place for the timer.  */ | ||||
|                     timer_list =  TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, expiration_time); | ||||
|                     if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(timer_list) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_end)) | ||||
|                     { | ||||
|  | ||||
|                         /* Wrap from the beginning of the list.  */ | ||||
|                         delta =  TX_TIMER_POINTER_DIF(timer_list, _tx_timer_list_end); | ||||
|                         timer_list =  TX_TIMER_POINTER_ADD(_tx_timer_list_start, delta); | ||||
|                     } | ||||
|  | ||||
|                     /* Now put the timer on this list.  */ | ||||
|                     if ((*timer_list) == TX_NULL) | ||||
|                     { | ||||
|  | ||||
|                         /* This list is NULL, just put the new timer on it.  */ | ||||
|  | ||||
|                         /* Setup the links in this timer.  */ | ||||
|                         current_timer -> tx_timer_internal_active_next =      current_timer; | ||||
|                         current_timer -> tx_timer_internal_active_previous =  current_timer; | ||||
|  | ||||
|                         /* Setup the list head pointer.  */ | ||||
|                         *timer_list =  current_timer; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|  | ||||
|                         /* This list is not NULL, add current timer to the end. */ | ||||
|                         next_timer =                                          *timer_list; | ||||
|                         previous_timer =                                      next_timer -> tx_timer_internal_active_previous; | ||||
|                         previous_timer -> tx_timer_internal_active_next =     current_timer; | ||||
|                         next_timer -> tx_timer_internal_active_previous =     current_timer; | ||||
|                         current_timer -> tx_timer_internal_active_next =      next_timer; | ||||
|                         current_timer -> tx_timer_internal_active_previous =  previous_timer; | ||||
|                     } | ||||
|  | ||||
|                     /* Setup list head pointer.  */ | ||||
|                     current_timer -> tx_timer_internal_list_head =  timer_list; | ||||
| #else | ||||
|  | ||||
|                     /* Reactivate through the timer activate function.  */ | ||||
|  | ||||
|                     /* Clear the list head for the timer activate call.  */ | ||||
|                     current_timer -> tx_timer_internal_list_head = TX_NULL; | ||||
|  | ||||
|                     /* Activate the current timer.  */ | ||||
|                     _tx_timer_system_activate(current_timer); | ||||
| #endif | ||||
|                 } | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Lockout interrupts again.  */ | ||||
|                 TX_DISABLE | ||||
|             } | ||||
|  | ||||
|             /* Finally, suspend this thread and wait for the next expiration.  */ | ||||
|  | ||||
|             /* Determine if another expiration took place while we were in this | ||||
|                thread.  If so, process another expiration.  */ | ||||
|             if (_tx_timer_expired == TX_FALSE) | ||||
|             { | ||||
|  | ||||
|                 /* Otherwise, no timer expiration, so suspend the thread.  */ | ||||
|  | ||||
|                 /* Build pointer to the timer thread.  */ | ||||
|                 thread_ptr =  &_tx_timer_thread; | ||||
|  | ||||
|                 /* Set the status to suspending, in order to indicate the | ||||
|                    suspension is in progress.  */ | ||||
|                 thread_ptr -> tx_thread_state =  TX_SUSPENDED; | ||||
|  | ||||
| #ifdef TX_NOT_INTERRUPTABLE | ||||
|  | ||||
|                 /* Call actual non-interruptable thread suspension routine.  */ | ||||
|                 _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0)); | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
| #else | ||||
|  | ||||
|                 /* Set the suspending flag. */ | ||||
|                 thread_ptr -> tx_thread_suspending =  TX_TRUE; | ||||
|  | ||||
|                 /* Increment the preempt disable count prior to suspending.  */ | ||||
|                 _tx_thread_preempt_disable++; | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|  | ||||
|                 /* Call actual thread suspension routine.  */ | ||||
|                 _tx_thread_system_suspend(thread_ptr); | ||||
| #endif | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Restore interrupts.  */ | ||||
|                 TX_RESTORE | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| #ifdef TX_SAFETY_CRITICAL | ||||
|  | ||||
|     /* If we ever get here, raise safety critical exception.  */ | ||||
|     TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0); | ||||
| #endif | ||||
|  | ||||
| } | ||||
| #endif | ||||
|  | ||||
							
								
								
									
										162
									
								
								Middlewares/ST/threadx/common/src/txe_block_allocate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								Middlewares/ST/threadx/common/src/txe_block_allocate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Block Pool                                                          */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_timer.h" | ||||
| #include "tx_block_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _txe_block_allocate                                 PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function checks for errors in the allocate block memory        */ | ||||
| /*    function call.                                                      */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                          Pointer to pool control block     */ | ||||
| /*    block_ptr                         Pointer to place allocated block  */ | ||||
| /*                                        pointer                         */ | ||||
| /*    wait_option                       Suspension option                 */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_POOL_ERROR                     Invalid pool pointer              */ | ||||
| /*    TX_PTR_ERROR                      Invalid destination pointer       */ | ||||
| /*    TX_WAIT_ERROR                     Invalid wait option               */ | ||||
| /*    status                            Actual Completion status          */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_block_allocate                Actual block allocate function    */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _txe_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option) | ||||
| { | ||||
|  | ||||
| UINT            status; | ||||
|  | ||||
| #ifndef TX_TIMER_PROCESS_IN_ISR | ||||
|  | ||||
| TX_THREAD       *current_thread; | ||||
| #endif | ||||
|  | ||||
|     /* Default status to success.  */ | ||||
|     status =  TX_SUCCESS; | ||||
|  | ||||
|     /* Check for an invalid pool pointer.  */ | ||||
|     if (pool_ptr == TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Pool pointer is invalid, return appropriate error code.  */ | ||||
|         status =  TX_POOL_ERROR; | ||||
|     } | ||||
|  | ||||
|     /* Check for an invalid pool pointer.  */ | ||||
|     else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID) | ||||
|     { | ||||
|  | ||||
|         /* Pool pointer is invalid, return appropriate error code.  */ | ||||
|         status =  TX_POOL_ERROR; | ||||
|     } | ||||
|  | ||||
|     /* Check for an invalid destination for return pointer.  */ | ||||
|     else if (block_ptr == TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Null destination pointer, return appropriate error.  */ | ||||
|         status =  TX_PTR_ERROR; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Check for a wait option error.  Only threads are allowed any form of | ||||
|            suspension.  */ | ||||
|         if (wait_option != TX_NO_WAIT) | ||||
|         { | ||||
|  | ||||
|             /* Is the call from an ISR or Initialization?  */ | ||||
|             if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) | ||||
|             { | ||||
|  | ||||
|                 /* A non-thread is trying to suspend, return appropriate error code.  */ | ||||
|                 status =  TX_WAIT_ERROR; | ||||
|             } | ||||
|  | ||||
| #ifndef TX_TIMER_PROCESS_IN_ISR | ||||
|             else | ||||
|             { | ||||
|  | ||||
|                 /* Pickup thread pointer.  */ | ||||
|                 TX_THREAD_GET_CURRENT(current_thread) | ||||
|  | ||||
|                 /* Is the current thread the timer thread?  */ | ||||
|                 if (current_thread == &_tx_timer_thread) | ||||
|                 { | ||||
|  | ||||
|                     /* A non-thread is trying to suspend, return appropriate error code.  */ | ||||
|                     status =  TX_WAIT_ERROR; | ||||
|                 } | ||||
|             } | ||||
| #endif | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Determine if everything is okay.  */ | ||||
|     if (status == TX_SUCCESS) | ||||
|     { | ||||
|  | ||||
|         /* Call actual block allocate function.  */ | ||||
|         status =  _tx_block_allocate(pool_ptr, block_ptr, wait_option); | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										229
									
								
								Middlewares/ST/threadx/common/src/txe_block_pool_create.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										229
									
								
								Middlewares/ST/threadx/common/src/txe_block_pool_create.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,229 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Block Pool                                                          */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_initialize.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_timer.h" | ||||
| #include "tx_block_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _txe_block_pool_create                              PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function checks for errors in the create block memory pool     */ | ||||
| /*    function call.                                                      */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                          Pointer to pool control block     */ | ||||
| /*    name_ptr                          Pointer to block pool name        */ | ||||
| /*    block_size                        Number of bytes in each block     */ | ||||
| /*    pool_start                        Address of beginning of pool area */ | ||||
| /*    pool_size                         Number of bytes in the block pool */ | ||||
| /*    pool_control_block_size           Size of block pool control block  */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_POOL_ERROR                     Invalid pool pointer              */ | ||||
| /*    TX_PTR_ERROR                      Invalid starting address          */ | ||||
| /*    TX_SIZE_ERROR                     Invalid pool size                 */ | ||||
| /*    TX_CALLER_ERROR                   Invalid caller of pool            */ | ||||
| /*    status                            Actual completion status          */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_block_pool_create             Actual block pool create function */ | ||||
| /*    _tx_thread_system_preempt_check   Check for preemption              */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, | ||||
|                     VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) | ||||
| { | ||||
|  | ||||
| TX_INTERRUPT_SAVE_AREA | ||||
|  | ||||
| UINT            status; | ||||
| ULONG           i; | ||||
| TX_BLOCK_POOL   *next_pool; | ||||
| #ifndef TX_TIMER_PROCESS_IN_ISR | ||||
| TX_THREAD       *thread_ptr; | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     /* Default status to success.  */ | ||||
|     status =  TX_SUCCESS; | ||||
|  | ||||
|     /* Check for an invalid pool pointer.  */ | ||||
|     if (pool_ptr == TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Pool pointer is invalid, return appropriate error code.  */ | ||||
|         status =  TX_POOL_ERROR; | ||||
|     } | ||||
|  | ||||
|     /* Check for invalid control block size.  */ | ||||
|     else if (pool_control_block_size != (sizeof(TX_BLOCK_POOL))) | ||||
|     { | ||||
|  | ||||
|         /* Pool pointer is invalid, return appropriate error code.  */ | ||||
|         status =  TX_POOL_ERROR; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Disable interrupts.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* Increment the preempt disable flag.  */ | ||||
|         _tx_thread_preempt_disable++; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Next see if it is already in the created list.  */ | ||||
|         next_pool =   _tx_block_pool_created_ptr; | ||||
|         for (i = ((ULONG) 0); i < _tx_block_pool_created_count; i++) | ||||
|         { | ||||
|  | ||||
|             /* Determine if this block pool matches the pool in the list.  */ | ||||
|             if (pool_ptr == next_pool) | ||||
|             { | ||||
|  | ||||
|                 break; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 /* Move to the next pool.  */ | ||||
|                 next_pool =  next_pool -> tx_block_pool_created_next; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Disable interrupts.  */ | ||||
|         TX_DISABLE | ||||
|  | ||||
|         /* Decrement the preempt disable flag.  */ | ||||
|         _tx_thread_preempt_disable--; | ||||
|  | ||||
|         /* Restore interrupts.  */ | ||||
|         TX_RESTORE | ||||
|  | ||||
|         /* Check for preemption.  */ | ||||
|         _tx_thread_system_preempt_check(); | ||||
|  | ||||
|         /* At this point, check to see if there is a duplicate pool.  */ | ||||
|         if (pool_ptr == next_pool) | ||||
|         { | ||||
|  | ||||
|             /* Pool is already created, return appropriate error code.  */ | ||||
|             status =  TX_POOL_ERROR; | ||||
|         } | ||||
|  | ||||
|         /* Check for an invalid starting address.  */ | ||||
|         else if (pool_start == TX_NULL) | ||||
|         { | ||||
|  | ||||
|             /* Null starting address pointer, return appropriate error.  */ | ||||
|             status =  TX_PTR_ERROR; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | ||||
|             /* Check for invalid pool size.  */ | ||||
|             if ((((block_size/(sizeof(void *)))*(sizeof(void *))) + (sizeof(void *))) > | ||||
|                                             ((pool_size/(sizeof(void *)))*(sizeof(void *)))) | ||||
|             { | ||||
|  | ||||
|                 /* Not enough memory for one block, return appropriate error.  */ | ||||
|                 status =  TX_SIZE_ERROR; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | ||||
| #ifndef TX_TIMER_PROCESS_IN_ISR | ||||
|  | ||||
|                 /* Pickup thread pointer.  */ | ||||
|                 TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
|                 /* 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.  */ | ||||
|                     status =  TX_CALLER_ERROR; | ||||
|                 } | ||||
| #endif | ||||
|  | ||||
|                 /* Check for interrupt call.  */ | ||||
|                 if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 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.  */ | ||||
|                         status =  TX_CALLER_ERROR; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Determine if everything is okay.  */ | ||||
|     if (status == TX_SUCCESS) | ||||
|     { | ||||
|  | ||||
|         /* Call actual block pool create function.  */ | ||||
|         status =  _tx_block_pool_create(pool_ptr, name_ptr, block_size, pool_start, pool_size); | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										148
									
								
								Middlewares/ST/threadx/common/src/txe_block_pool_delete.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								Middlewares/ST/threadx/common/src/txe_block_pool_delete.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Block Pool                                                          */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_thread.h" | ||||
| #include "tx_timer.h" | ||||
| #include "tx_block_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _txe_block_pool_delete                              PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function checks for errors in the delete block pool memory     */ | ||||
| /*    function call.                                                      */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                          Pointer to pool control block     */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_POOL_ERROR                     Invalid memory block pool pointer */ | ||||
| /*    TX_CALLER_ERROR                   Invalid caller of this function   */ | ||||
| /*    status                            Actual delete function status     */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_block_pool_delete             Actual block pool delete function */ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT    _txe_block_pool_delete(TX_BLOCK_POOL *pool_ptr) | ||||
| { | ||||
|  | ||||
| UINT        status; | ||||
| #ifndef TX_TIMER_PROCESS_IN_ISR | ||||
| TX_THREAD   *thread_ptr; | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #ifndef TX_TIMER_PROCESS_IN_ISR | ||||
|  | ||||
|     /* Default status to success.  */ | ||||
|     status =  TX_SUCCESS; | ||||
| #endif | ||||
|  | ||||
|     /* Check for an invalid pool pointer.  */ | ||||
|     if (pool_ptr == TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Pool pointer is invalid, return appropriate error code.  */ | ||||
|         status =  TX_POOL_ERROR; | ||||
|     } | ||||
|  | ||||
|     /* Now check the pool ID.  */ | ||||
|     else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID) | ||||
|     { | ||||
|  | ||||
|         /* Pool pointer is invalid, return appropriate error code.  */ | ||||
|         status =  TX_POOL_ERROR; | ||||
|     } | ||||
|  | ||||
|     /* Check for invalid caller of this function.  */ | ||||
|  | ||||
|     /* Is the call from an ISR or initialization?  */ | ||||
|     else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) | ||||
|     { | ||||
|  | ||||
|         /* Invalid caller of this function, return appropriate error code.  */ | ||||
|         status =  TX_CALLER_ERROR; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
| #ifndef TX_TIMER_PROCESS_IN_ISR | ||||
|  | ||||
|         /* Pickup thread pointer.  */ | ||||
|         TX_THREAD_GET_CURRENT(thread_ptr) | ||||
|  | ||||
|         /* Is the call from the system timer thread?  */ | ||||
|         if (thread_ptr == &_tx_timer_thread) | ||||
|         { | ||||
|  | ||||
|             /* Invalid caller of this function, return appropriate error code.  */ | ||||
|             status =  TX_CALLER_ERROR; | ||||
|         } | ||||
|  | ||||
|         /* Determine if everything is okay.  */ | ||||
|         if (status == TX_SUCCESS) | ||||
|         { | ||||
| #endif | ||||
|  | ||||
|             /* Call actual block pool delete function.  */ | ||||
|             status =  _tx_block_pool_delete(pool_ptr); | ||||
|  | ||||
| #ifndef TX_TIMER_PROCESS_IN_ISR | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
							
								
								
									
										116
									
								
								Middlewares/ST/threadx/common/src/txe_block_pool_info_get.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								Middlewares/ST/threadx/common/src/txe_block_pool_info_get.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*       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                                                     */ | ||||
| /**                                                                       */ | ||||
| /**   Block Memory                                                        */ | ||||
| /**                                                                       */ | ||||
| /**************************************************************************/ | ||||
| /**************************************************************************/ | ||||
|  | ||||
| #define TX_SOURCE_CODE | ||||
|  | ||||
|  | ||||
| /* Include necessary system files.  */ | ||||
|  | ||||
| #include "tx_api.h" | ||||
| #include "tx_block_pool.h" | ||||
|  | ||||
|  | ||||
| /**************************************************************************/ | ||||
| /*                                                                        */ | ||||
| /*  FUNCTION                                               RELEASE        */ | ||||
| /*                                                                        */ | ||||
| /*    _txe_block_pool_info_get                            PORTABLE C      */ | ||||
| /*                                                           6.1          */ | ||||
| /*  AUTHOR                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    William E. Lamie, Microsoft Corporation                             */ | ||||
| /*                                                                        */ | ||||
| /*  DESCRIPTION                                                           */ | ||||
| /*                                                                        */ | ||||
| /*    This function checks for errors in the block pool information get   */ | ||||
| /*    service.                                                            */ | ||||
| /*                                                                        */ | ||||
| /*  INPUT                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    pool_ptr                          Pointer to block pool control blk */ | ||||
| /*    name                              Destination for the pool name     */ | ||||
| /*    available_blocks                  Number of free blocks in pool     */ | ||||
| /*    total_blocks                      Total number of blocks in pool    */ | ||||
| /*    first_suspended                   Destination for pointer of first  */ | ||||
| /*                                        thread suspended on block pool  */ | ||||
| /*    suspended_count                   Destination for suspended count   */ | ||||
| /*    next_pool                         Destination for pointer to next   */ | ||||
| /*                                        block pool on the created list  */ | ||||
| /*                                                                        */ | ||||
| /*  OUTPUT                                                                */ | ||||
| /*                                                                        */ | ||||
| /*    TX_POOL_ERROR                     Invalid block pool pointer        */ | ||||
| /*    status                            Completion status                 */ | ||||
| /*                                                                        */ | ||||
| /*  CALLS                                                                 */ | ||||
| /*                                                                        */ | ||||
| /*    _tx_block_pool_info_get           Actual block pool info get service*/ | ||||
| /*                                                                        */ | ||||
| /*  CALLED BY                                                             */ | ||||
| /*                                                                        */ | ||||
| /*    Application Code                                                    */ | ||||
| /*                                                                        */ | ||||
| /*  RELEASE HISTORY                                                       */ | ||||
| /*                                                                        */ | ||||
| /*    DATE              NAME                      DESCRIPTION             */ | ||||
| /*                                                                        */ | ||||
| /*  05-19-2020     William E. Lamie         Initial Version 6.0           */ | ||||
| /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */ | ||||
| /*                                            resulting in version 6.1    */ | ||||
| /*                                                                        */ | ||||
| /**************************************************************************/ | ||||
| UINT  _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, | ||||
|                     ULONG *total_blocks, TX_THREAD **first_suspended, | ||||
|                     ULONG *suspended_count, TX_BLOCK_POOL **next_pool) | ||||
| { | ||||
|  | ||||
|  | ||||
| UINT    status; | ||||
|  | ||||
|  | ||||
|     /* Check for an invalid block pool pointer.  */ | ||||
|     if (pool_ptr == TX_NULL) | ||||
|     { | ||||
|  | ||||
|         /* Block pool pointer is invalid, return appropriate error code.  */ | ||||
|         status =  TX_POOL_ERROR; | ||||
|     } | ||||
|  | ||||
|     /* Now check the pool ID.  */ | ||||
|     else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID) | ||||
|     { | ||||
|  | ||||
|         /* Block pool pointer is invalid, return appropriate error code.  */ | ||||
|         status =  TX_POOL_ERROR; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | ||||
|         /* Otherwise, call the actual block pool information get service.  */ | ||||
|         status =  _tx_block_pool_info_get(pool_ptr, name, available_blocks, | ||||
|                         total_blocks, first_suspended, suspended_count, next_pool); | ||||
|     } | ||||
|  | ||||
|     /* Return completion status.  */ | ||||
|     return(status); | ||||
| } | ||||
|  | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	 chauyin
					chauyin