summaryrefslogtreecommitdiff
path: root/common/src/tx_trace_enable.c
diff options
context:
space:
mode:
authorPProvost <[email protected]>2020-05-11 08:55:07 -0600
committerPProvost <[email protected]>2020-05-11 08:55:07 -0600
commit852421fda03a7722d7adb45b187235cd66fa264e (patch)
treeb117e1339a047347a3d7ebf3eeb1891168cc9b9b /common/src/tx_trace_enable.c
Initial commit
Diffstat (limited to 'common/src/tx_trace_enable.c')
-rw-r--r--common/src/tx_trace_enable.c442
1 files changed, 442 insertions, 0 deletions
diff --git a/common/src/tx_trace_enable.c b/common/src/tx_trace_enable.c
new file mode 100644
index 00000000..079500fd
--- /dev/null
+++ b/common/src/tx_trace_enable.c
@@ -0,0 +1,442 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Trace */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#ifdef TX_ENABLE_EVENT_TRACE
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_event_flags.h"
+#include "tx_queue.h"
+#include "tx_semaphore.h"
+#include "tx_mutex.h"
+#include "tx_block_pool.h"
+#include "tx_byte_pool.h"
+#endif
+#include "tx_trace.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_trace_enable PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes the ThreadX trace buffer and the */
+/* associated control variables, enabling it for operation. */
+/* */
+/* INPUT */
+/* */
+/* trace_buffer_start Start of trace buffer */
+/* trace_buffer_size Size (bytes) of trace buffer */
+/* registry_entries Number of object registry */
+/* entries. */
+/* */
+/* OUTPUT */
+/* */
+/* Completion Status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_system_preempt_check Check for preemption */
+/* _tx_trace_object_register Register existing objects */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+UINT _tx_trace_enable(VOID *trace_buffer_start, ULONG trace_buffer_size, ULONG registry_entries)
+{
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD *thread_ptr;
+TX_TIMER *timer_ptr;
+TX_EVENT_FLAGS_GROUP *event_flags_ptr;
+TX_QUEUE *queue_ptr;
+TX_SEMAPHORE *semaphore_ptr;
+TX_MUTEX *mutex_ptr;
+TX_BLOCK_POOL *block_pool_ptr;
+TX_BYTE_POOL *byte_pool_ptr;
+UCHAR *work_ptr;
+UCHAR *event_start_ptr;
+TX_TRACE_OBJECT_ENTRY *entry_ptr;
+TX_TRACE_BUFFER_ENTRY *event_ptr;
+ULONG i;
+UINT status;
+
+
+ /* First, see if there is enough room for the control header, the registry entries, and at least one event in
+ memory supplied to this call. */
+ if (trace_buffer_size < ((sizeof(TX_TRACE_HEADER)) + ((sizeof(TX_TRACE_OBJECT_ENTRY)) * registry_entries) + (sizeof(TX_TRACE_BUFFER_ENTRY))))
+ {
+
+ /* No, the memory isn't big enough to hold one trace buffer entry. Return an error. */
+ status = TX_SIZE_ERROR;
+ }
+
+ /* Determine if trace is already enabled. */
+ else if (_tx_trace_buffer_current_ptr != TX_NULL)
+ {
+
+ /* Yes, trace is already enabled. */
+ status = TX_NOT_DONE;
+ }
+ else
+ {
+
+ /* Set the enable bits for all events enabled. */
+ _tx_trace_event_enable_bits = 0xFFFFFFFFUL;
+
+ /* Setup working pointer to the supplied memory. */
+ work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(trace_buffer_start);
+
+ /* Setup pointer to the trace control area. */
+ _tx_trace_header_ptr = TX_UCHAR_TO_HEADER_POINTER_CONVERT(work_ptr);
+
+ /* Move the working pointer past the control area. */
+ work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(TX_TRACE_HEADER)));
+
+ /* Save the start of the trace object registry. */
+ _tx_trace_registry_start_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr);
+
+ /* Setup the end of the trace object registry. */
+ work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(TX_TRACE_OBJECT_ENTRY))*registry_entries);
+ _tx_trace_registry_end_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr);
+
+ /* Loop to make all trace object registry entries empty and valid. */
+ for (i = ((ULONG) 0); i < registry_entries; i++)
+ {
+
+ /* Setup the work pointer. */
+ work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_start_ptr);
+ work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(TX_TRACE_OBJECT_ENTRY))*i);
+
+ /* Convert to a registry entry pointer. */
+ entry_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr);
+
+ /* Initialize object registry entry. */
+ entry_ptr -> tx_trace_object_entry_available = (UCHAR) TX_TRUE;
+ entry_ptr -> tx_trace_object_entry_type = (UCHAR) TX_TRACE_OBJECT_TYPE_NOT_VALID;
+ entry_ptr -> tx_trace_object_entry_reserved1 = (UCHAR) 0;
+ entry_ptr -> tx_trace_object_entry_reserved2 = (UCHAR) 0;
+ entry_ptr -> tx_trace_object_entry_thread_pointer = (ULONG) 0;
+ }
+
+ /* Setup the total number of registry entries. */
+ _tx_trace_total_registry_entries = registry_entries;
+
+ /* Setup the object registry available count to the total number of registry entries. */
+ _tx_trace_available_registry_entries = registry_entries;
+
+ /* Setup the search starting index to the first entry. */
+ _tx_trace_registry_search_start = ((ULONG) 0);
+
+ /* Setup the work pointer to after the trace object registry. */
+ work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_end_ptr);
+
+ /* Adjust the remaining trace buffer size. */
+ trace_buffer_size = trace_buffer_size - ((sizeof(TX_TRACE_OBJECT_ENTRY)) * registry_entries) - (sizeof(TX_TRACE_HEADER));
+
+ /* Setup pointer to the start of the actual event trace log. */
+ _tx_trace_buffer_start_ptr = TX_UCHAR_TO_ENTRY_POINTER_CONVERT(work_ptr);
+
+ /* Save the event trace log start address. */
+ event_start_ptr = work_ptr;
+
+ /* Calculate the end of the trace buffer. */
+ work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, ((trace_buffer_size/(sizeof(TX_TRACE_BUFFER_ENTRY)))*(sizeof(TX_TRACE_BUFFER_ENTRY))));
+ _tx_trace_buffer_end_ptr = TX_UCHAR_TO_ENTRY_POINTER_CONVERT(work_ptr);
+
+ /* Loop to mark all entries in the trace buffer as invalid. */
+ for (i = ((ULONG) 0); i < (trace_buffer_size/(sizeof(TX_TRACE_BUFFER_ENTRY))); i++)
+ {
+
+ /* Setup the work pointer. */
+ work_ptr = TX_UCHAR_POINTER_ADD(event_start_ptr, (sizeof(TX_TRACE_BUFFER_ENTRY))*i);
+
+ /* Convert to a trace event pointer. */
+ event_ptr = TX_UCHAR_TO_ENTRY_POINTER_CONVERT(work_ptr);
+
+ /* Mark this trace event as invalid. */
+ event_ptr -> tx_trace_buffer_entry_thread_pointer = ((ULONG) 0);
+ }
+
+ /* Now, fill in the event trace control header. */
+ _tx_trace_header_ptr -> tx_trace_header_id = TX_TRACE_VALID;
+ _tx_trace_header_ptr -> tx_trace_header_timer_valid_mask = TX_TRACE_TIME_MASK;
+ _tx_trace_header_ptr -> tx_trace_header_trace_base_address = TX_POINTER_TO_ULONG_CONVERT(trace_buffer_start);
+ _tx_trace_header_ptr -> tx_trace_header_registry_start_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_registry_start_ptr);
+ _tx_trace_header_ptr -> tx_trace_header_reserved1 = ((USHORT) 0);
+ _tx_trace_header_ptr -> tx_trace_header_object_name_size = ((USHORT) TX_TRACE_OBJECT_REGISTRY_NAME);
+ _tx_trace_header_ptr -> tx_trace_header_registry_end_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_registry_end_ptr);
+ _tx_trace_header_ptr -> tx_trace_header_buffer_start_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_buffer_start_ptr);
+ _tx_trace_header_ptr -> tx_trace_header_buffer_end_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_buffer_end_ptr);
+ _tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_buffer_start_ptr);
+ _tx_trace_header_ptr -> tx_trace_header_reserved2 = 0xAAAAAAAAUL;
+ _tx_trace_header_ptr -> tx_trace_header_reserved3 = 0xBBBBBBBBUL;
+ _tx_trace_header_ptr -> tx_trace_header_reserved4 = 0xCCCCCCCCUL;
+
+ /* Now, loop through all existing ThreadX objects and register them in the newly setup trace buffer. */
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* First, disable preemption. */
+ _tx_thread_preempt_disable++;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Pickup the first thread and the number of created threads. */
+ thread_ptr = _tx_thread_created_ptr;
+ i = _tx_thread_created_count;
+
+ /* Loop to register all threads. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this thread. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_THREAD, thread_ptr, thread_ptr -> tx_thread_name,
+ TX_POINTER_TO_ULONG_CONVERT(thread_ptr -> tx_thread_stack_start), (ULONG) thread_ptr -> tx_thread_stack_size);
+
+ /* Move to the next thread. */
+ thread_ptr = thread_ptr -> tx_thread_created_next;
+ }
+
+ /* Pickup the first timer and the number of created timers. */
+ timer_ptr = _tx_timer_created_ptr;
+ i = _tx_timer_created_count;
+
+ /* Loop to register all timers. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this timer. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_TIMER, timer_ptr, timer_ptr -> tx_timer_name,
+ ((ULONG) 0), timer_ptr -> tx_timer_internal.tx_timer_internal_re_initialize_ticks);
+
+ /* Move to the next timer. */
+ timer_ptr = timer_ptr -> tx_timer_created_next;
+ }
+
+
+ /* Pickup the first event flag group and the number of created groups. */
+ event_flags_ptr = _tx_event_flags_created_ptr;
+ i = _tx_event_flags_created_count;
+
+ /* Loop to register all event flags groups. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this event flags group. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_EVENT_FLAGS, event_flags_ptr, event_flags_ptr -> tx_event_flags_group_name, ((ULONG) 0), ((ULONG) 0));
+
+ /* Move to the next event flags group. */
+ event_flags_ptr = event_flags_ptr -> tx_event_flags_group_created_next;
+ }
+
+ /* Pickup the first queue and the number of created queues. */
+ queue_ptr = _tx_queue_created_ptr;
+ i = _tx_queue_created_count;
+
+ /* Loop to register all queues. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this queue. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_QUEUE, queue_ptr, queue_ptr -> tx_queue_name,
+ (queue_ptr -> tx_queue_capacity * (sizeof(ULONG))), ((ULONG) 0));
+
+ /* Move to the next queue. */
+ queue_ptr = queue_ptr -> tx_queue_created_next;
+ }
+
+ /* Pickup the first semaphore and the number of created semaphores. */
+ semaphore_ptr = _tx_semaphore_created_ptr;
+ i = _tx_semaphore_created_count;
+
+ /* Loop to register all semaphores. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this semaphore. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_SEMAPHORE, semaphore_ptr, semaphore_ptr -> tx_semaphore_name, ((ULONG) 0), ((ULONG) 0));
+
+ /* Move to the next semaphore. */
+ semaphore_ptr = semaphore_ptr -> tx_semaphore_created_next;
+ }
+
+ /* Pickup the first mutex and the number of created mutexes. */
+ mutex_ptr = _tx_mutex_created_ptr;
+ i = _tx_mutex_created_count;
+
+ /* Loop to register all mutexes. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this mutex. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_MUTEX, mutex_ptr, mutex_ptr -> tx_mutex_name,
+ (ULONG) mutex_ptr -> tx_mutex_inherit, ((ULONG) 0));
+
+ /* Move to the next mutex. */
+ mutex_ptr = mutex_ptr -> tx_mutex_created_next;
+ }
+
+ /* Pickup the first block pool and the number of created block pools. */
+ block_pool_ptr = _tx_block_pool_created_ptr;
+ i = _tx_block_pool_created_count;
+
+ /* Loop to register all block pools. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this block pool. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_BLOCK_POOL, block_pool_ptr, block_pool_ptr -> tx_block_pool_name,
+ block_pool_ptr -> tx_block_pool_size, ((ULONG) 0));
+
+ /* Move to the next block pool. */
+ block_pool_ptr = block_pool_ptr -> tx_block_pool_created_next;
+ }
+
+ /* Pickup the first byte pool and the number of created byte pools. */
+ byte_pool_ptr = _tx_byte_pool_created_ptr;
+ i = _tx_byte_pool_created_count;
+
+ /* Loop to register all byte pools. */
+ while (i != ((ULONG) 0))
+ {
+
+ /* Decrement the counter. */
+ i--;
+
+ /* Register this byte pool. */
+ _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_BYTE_POOL, byte_pool_ptr, byte_pool_ptr -> tx_byte_pool_name,
+ byte_pool_ptr -> tx_byte_pool_size, ((ULONG) 0));
+
+ /* Move to the next byte pool. */
+ byte_pool_ptr = byte_pool_ptr -> tx_byte_pool_created_next;
+ }
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Release the preeemption. */
+ _tx_thread_preempt_disable--;
+
+ /* Finally, setup the current buffer pointer, which effectively enables the trace! */
+ _tx_trace_buffer_current_ptr = (TX_TRACE_BUFFER_ENTRY *) _tx_trace_buffer_start_ptr;
+
+ /* Insert two RUNNING events so the buffer is not empty. */
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_RUNNING, 0, 0, 0, 0, TX_TRACE_INTERNAL_EVENTS)
+ TX_TRACE_IN_LINE_INSERT(TX_TRACE_RUNNING, 0, 0, 0, 0, TX_TRACE_INTERNAL_EVENTS)
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Check for preemption. */
+ _tx_thread_system_preempt_check();
+
+ /* Return successful completion. */
+ status = TX_SUCCESS;
+ }
+
+ /* Return completion status. */
+ return(status);
+#else
+
+UINT status;
+
+
+ /* Access input arguments just for the sake of lint, MISRA, etc. */
+ if (trace_buffer_start != TX_NULL)
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (trace_buffer_size == ((ULONG) 0))
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else if (registry_entries == ((ULONG) 0))
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+ else
+ {
+
+ /* Trace not enabled, return an error. */
+ status = TX_FEATURE_NOT_ENABLED;
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
+
+
+