source: rtems/testsuites/sptests/spintrcritical_support/intrcritical.c @ af92665

Last change on this file since af92665 was af92665, checked in by Sebastian Huber <sebastian.huber@…>, on 07/17/20 at 12:49:42

libtest: Add T_get_one_clock_tick_busy()

Update #3199.

  • Property mode set to 100644
File size: 3.9 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-2009.
3 *  On-Line Applications Research Corporation (OAR).
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.rtems.org/license/LICENSE.
8 */
9
10#ifdef HAVE_CONFIG_H
11#include "config.h"
12#endif
13
14#include <tmacros.h>
15#include <intrcritical.h>
16#include <rtems/test.h>
17
18#define INTERRUPT_CRITICAL_NAME rtems_build_name( 'I', 'C', 'R', 'I' )
19
20typedef struct {
21  uint_fast32_t minimum;
22  uint_fast32_t maximum;
23  uint_fast32_t maximum_current;
24  rtems_timer_service_routine_entry tsr;
25  rtems_id timer;
26  uint64_t t0;
27  uint64_t t1;
28} interrupt_critical_control;
29
30static interrupt_critical_control interrupt_critical;
31
32static void wait_for_tick_change( void )
33{
34  rtems_interval initial = rtems_clock_get_ticks_since_boot();
35  rtems_interval now;
36
37  do {
38    now = rtems_clock_get_ticks_since_boot();
39  } while ( now == initial );
40}
41
42static bool interrupt_critical_busy_wait( void )
43{
44  uint_fast32_t max = interrupt_critical.maximum_current;
45  bool reset = max <= interrupt_critical.minimum;
46
47  if ( reset ) {
48    interrupt_critical.maximum_current = interrupt_critical.maximum;
49  } else {
50    interrupt_critical.maximum_current = max - 1;
51  }
52
53  T_busy( max );
54
55  return reset;
56}
57
58void interrupt_critical_section_test_support_initialize(
59  rtems_timer_service_routine_entry tsr
60)
61{
62  uint_fast32_t m;
63
64  interrupt_critical.tsr = tsr;
65
66  if ( tsr != NULL && interrupt_critical.timer == 0 ) {
67    rtems_status_code sc = rtems_timer_create(
68      INTERRUPT_CRITICAL_NAME,
69      &interrupt_critical.timer
70    );
71    rtems_test_assert( sc == RTEMS_SUCCESSFUL );
72  }
73
74  m = T_get_one_clock_tick_busy();
75
76  interrupt_critical.minimum = 0;
77  interrupt_critical.maximum = m;
78  interrupt_critical.maximum_current = m;
79}
80
81static void timer_fire_after(void)
82{
83  if ( interrupt_critical.tsr != NULL ) {
84    rtems_status_code sc = rtems_timer_fire_after(
85      interrupt_critical.timer,
86      1,
87      interrupt_critical.tsr,
88      NULL
89    );
90    rtems_test_assert( sc == RTEMS_SUCCESSFUL );
91  }
92}
93
94bool interrupt_critical_section_test_support_delay(void)
95{
96  timer_fire_after();
97
98  return interrupt_critical_busy_wait();
99}
100
101static void thread_switch( Thread_Control *executing, Thread_Control *heir )
102{
103  (void) executing;
104  (void) heir;
105
106  if ( interrupt_critical.t1 == 0 && heir->is_idle ) {
107    interrupt_critical.t1 = rtems_clock_get_uptime_nanoseconds();
108  }
109}
110
111static const rtems_extensions_table extensions = {
112  .thread_switch = thread_switch
113};
114
115bool interrupt_critical_section_test(
116  bool                              ( *test_body )( void * ),
117  void                                *test_body_arg,
118  rtems_timer_service_routine_entry    tsr
119)
120{
121  bool done;
122  rtems_status_code sc;
123  rtems_id id;
124  uint64_t delta;
125  uint_fast32_t busy_delta;
126  int retries = 3;
127
128  interrupt_critical_section_test_support_initialize( tsr );
129
130  sc = rtems_extension_create(
131    INTERRUPT_CRITICAL_NAME,
132    &extensions,
133    &id
134  );
135  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
136
137  wait_for_tick_change();
138  timer_fire_after();
139
140  /* Get estimate for test body duration */
141  interrupt_critical.t0 = rtems_clock_get_uptime_nanoseconds();
142  done = ( *test_body )( test_body_arg );
143  if ( interrupt_critical.t1 == 0 ) {
144    interrupt_critical.t1 = rtems_clock_get_uptime_nanoseconds();
145  }
146
147  /* Update minimum */
148
149  delta = interrupt_critical.t1 - interrupt_critical.t0;
150  busy_delta = (uint_fast32_t)
151    ( ( interrupt_critical.maximum * ( 2 * delta ) )
152      / rtems_configuration_get_nanoseconds_per_tick() );
153
154  if ( busy_delta < interrupt_critical.maximum ) {
155    interrupt_critical.minimum = interrupt_critical.maximum - busy_delta;
156  }
157
158  sc = rtems_extension_delete( id );
159  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
160
161  while ( !done && retries >= 0 ) {
162    wait_for_tick_change();
163
164    if ( interrupt_critical_section_test_support_delay() ) {
165      --retries;
166    }
167
168    done = ( *test_body )( test_body_arg );
169  }
170
171  return done;
172}
Note: See TracBrowser for help on using the repository browser.