File indexing completed on 2025-05-11 08:24:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #ifdef HAVE_CONFIG_H
0038 #include "config.h"
0039 #endif
0040
0041 #include <rtems/test.h>
0042
0043 #include <rtems.h>
0044 #include <rtems/score/percpu.h>
0045 #include <rtems/score/smp.h>
0046 #include <rtems/score/thread.h>
0047 #include <rtems/score/userextimpl.h>
0048
0049 typedef struct {
0050 RTEMS_INTERRUPT_LOCK_MEMBER(lock)
0051 T_thread_switch_log *active;
0052 User_extensions_Control ext;
0053 T_destructor dtor;
0054 } T_thread_switch_context;
0055
0056 static void T_thread_switch_recorder(Thread_Control *, Thread_Control *);
0057
0058 static T_thread_switch_context T_thread_switch_instance = {
0059 #ifdef RTEMS_SMP
0060 .lock = RTEMS_INTERRUPT_LOCK_INITIALIZER("Test Thread Switches"),
0061 #endif
0062 .ext = {
0063 .Callouts = {
0064 .thread_switch = T_thread_switch_recorder
0065 }
0066 }
0067 };
0068
0069 static void
0070 T_thread_switch_destroy(T_destructor *dtor)
0071 {
0072 T_thread_switch_context *ctx;
0073
0074 ctx = RTEMS_CONTAINER_OF(dtor, T_thread_switch_context, dtor);
0075 _User_extensions_Remove_set(&ctx->ext);
0076 _Chain_Set_off_chain(&ctx->ext.Node);
0077 }
0078
0079 static void
0080 T_thread_switch_recorder(Thread_Control *executing, Thread_Control *heir)
0081 {
0082 rtems_interrupt_lock_context lock_context;
0083 T_thread_switch_context *ctx;
0084 T_thread_switch_log *log;
0085
0086 ctx = &T_thread_switch_instance;
0087
0088 #ifdef RTEMS_SMP
0089 if (ctx->active == NULL) {
0090 return;
0091 }
0092 #endif
0093
0094 rtems_interrupt_lock_acquire_isr(&ctx->lock, &lock_context);
0095 log = ctx->active;
0096
0097 if (log != NULL) {
0098 size_t recorded;
0099
0100 ++log->header.switches;
0101 recorded = log->header.recorded;
0102
0103 if (recorded < log->header.capacity) {
0104 log->header.recorded = recorded + 1;
0105 log->events[recorded].executing = executing->Object.id;
0106 log->events[recorded].heir = heir->Object.id;
0107 log->events[recorded].cpu =
0108 _SMP_Get_current_processor();
0109 log->events[recorded].instant = T_now();
0110 }
0111 }
0112
0113 rtems_interrupt_lock_release_isr(&ctx->lock, &lock_context);
0114 }
0115
0116 T_thread_switch_log *
0117 T_thread_switch_record(T_thread_switch_log *log)
0118 {
0119 rtems_interrupt_lock_context lock_context;
0120 T_thread_switch_log *previous;
0121 T_thread_switch_context *ctx;
0122
0123 ctx = &T_thread_switch_instance;
0124
0125 if (_Chain_Is_node_off_chain(&ctx->ext.Node)) {
0126 _User_extensions_Add_set(&ctx->ext);
0127 T_add_destructor(&ctx->dtor, T_thread_switch_destroy);
0128 }
0129
0130 if (log != NULL) {
0131 log->header.recorded = 0;
0132 log->header.switches = 0;
0133 }
0134
0135 rtems_interrupt_lock_acquire(&ctx->lock, &lock_context);
0136 previous = ctx->active;
0137 ctx->active = log;
0138 rtems_interrupt_lock_release(&ctx->lock, &lock_context);
0139
0140 return previous;
0141 }
0142
0143 T_thread_switch_log *
0144 T_thread_switch_record_2(T_thread_switch_log_2 *log)
0145 {
0146 log->header.capacity = T_ARRAY_SIZE(log->events);
0147 return T_thread_switch_record((T_thread_switch_log *)log);
0148 }
0149
0150 T_thread_switch_log *
0151 T_thread_switch_record_4(T_thread_switch_log_4 *log)
0152 {
0153 log->header.capacity = T_ARRAY_SIZE(log->events);
0154 return T_thread_switch_record((T_thread_switch_log *)log);
0155 }
0156
0157 T_thread_switch_log *
0158 T_thread_switch_record_10(T_thread_switch_log_10 *log)
0159 {
0160 log->header.capacity = T_ARRAY_SIZE(log->events);
0161 return T_thread_switch_record((T_thread_switch_log *)log);
0162 }