RTEMS
t-test-thread-switch.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 
11 /*
12  * Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  * notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  * notice, this list of conditions and the following disclaimer in the
21  * documentation and/or other materials provided with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39 
40 #include <rtems/test.h>
41 
42 #include <rtems.h>
43 #include <rtems/score/percpu.h>
44 #include <rtems/score/smp.h>
45 #include <rtems/score/thread.h>
47 
48 typedef struct {
50  T_thread_switch_log *active;
52  T_destructor dtor;
54 
55 static void T_thread_switch_recorder(Thread_Control *, Thread_Control *);
56 
57 static T_thread_switch_context T_thread_switch_instance = {
58 #ifdef RTEMS_SMP
59  .lock = RTEMS_INTERRUPT_LOCK_INITIALIZER("Test Thread Switches"),
60 #endif
61  .ext = {
62  .Callouts = {
63  .thread_switch = T_thread_switch_recorder
64  }
65  }
66 };
67 
68 static void
69 T_thread_switch_destroy(T_destructor *dtor)
70 {
72 
74  _User_extensions_Remove_set(&ctx->ext);
75  _Chain_Set_off_chain(&ctx->ext.Node);
76 }
77 
78 static void
79 T_thread_switch_recorder(Thread_Control *executing, Thread_Control *heir)
80 {
81  rtems_interrupt_lock_context lock_context;
84 
85  ctx = &T_thread_switch_instance;
86 
87 #ifdef RTEMS_SMP
88  if (ctx->active == NULL) {
89  return;
90  }
91 #endif
92 
93  rtems_interrupt_lock_acquire_isr(&ctx->lock, &lock_context);
94  log = ctx->active;
95 
96  if (log != NULL) {
97  size_t recorded;
98 
99  ++log->switches;
100  recorded = log->recorded;
101 
102  if (recorded < log->capacity) {
103  log->recorded = recorded + 1;
104  log->events[recorded].executing = executing->Object.id;
105  log->events[recorded].heir = heir->Object.id;
106  log->events[recorded].cpu =
107  _SMP_Get_current_processor();
108  log->events[recorded].instant = T_now();
109  }
110  }
111 
112  rtems_interrupt_lock_release_isr(&ctx->lock, &lock_context);
113 }
114 
116 T_thread_switch_record(T_thread_switch_log *log)
117 {
118  rtems_interrupt_lock_context lock_context;
119  T_thread_switch_log *previous;
121 
122  ctx = &T_thread_switch_instance;
123 
124  if (_Chain_Is_node_off_chain(&ctx->ext.Node)) {
125  _User_extensions_Add_set(&ctx->ext);
126  T_add_destructor(&ctx->dtor, T_thread_switch_destroy);
127  }
128 
129  if (log != NULL) {
130  log->recorded = 0;
131  log->switches = 0;
132  }
133 
134  rtems_interrupt_lock_acquire(&ctx->lock, &lock_context);
135  previous = ctx->active;
136  ctx->active = log;
137  rtems_interrupt_lock_release(&ctx->lock, &lock_context);
138 
139  return previous;
140 }
141 
143 T_thread_switch_record_2(T_thread_switch_log_2 *log)
144 {
145  log->log.capacity = 2;
146  return T_thread_switch_record(&log->log);
147 }
148 
150 T_thread_switch_record_4(T_thread_switch_log_4 *log)
151 {
152  log->log.capacity = 4;
153  return T_thread_switch_record(&log->log);
154 }
155 
157 T_thread_switch_record_10(T_thread_switch_log_10 *log)
158 {
159  log->log.capacity = 10;
160  return T_thread_switch_record(&log->log);
161 }
#define RTEMS_INTERRUPT_LOCK_MEMBER(_designator)
%
Definition: intr.h:378
static __inline__ bool _Chain_Is_node_off_chain(const Chain_Node *node)
Checks if the node is off chain.
Definition: chainimpl.h:142
#define rtems_interrupt_lock_release_isr(_lock, _lock_context)
%
Definition: intr.h:421
User Extension Handler API.
SuperCore SMP Support API.
#define RTEMS_CONTAINER_OF(_m, _type, _member_name)
Returns the pointer to the container of a specified member pointer.
Definition: basedefs.h:550
void _User_extensions_Add_set(User_extensions_Control *extension)
Adds a user extension.
Definition: userextaddset.c:45
void _User_extensions_Remove_set(User_extensions_Control *extension)
Removes a user extension.
Objects_Control Object
Definition: thread.h:727
This header file defines the RTEMS Classic API.
#define RTEMS_INTERRUPT_LOCK_INITIALIZER(_name)
%
Definition: intr.h:355
Manages each user extension set.
Definition: userextdata.h:50
static __inline__ void _Chain_Set_off_chain(Chain_Node *node)
Sets off chain.
Definition: chainimpl.h:104
Local ISR lock context for acquire and release pairs.
Definition: isrlock.h:65
#define rtems_interrupt_lock_acquire_isr(_lock, _lock_context)
%
Definition: intr.h:272
Constants and Structures Related with the Thread Control Block.
#define rtems_interrupt_lock_release(_lock, _lock_context)
%
Definition: intr.h:406
#define rtems_interrupt_lock_acquire(_lock, _lock_context)
%
Definition: intr.h:257
Objects_Id id
Definition: objectdata.h:43