summaryrefslogtreecommitdiffstats
path: root/cpukit/libtest/testbusy.c
blob: bf11b11632b7464bb454d4e02a17bfe92a47d5d4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
 * Copyright (c) 2014, 2018 embedded brains GmbH.  All rights reserved.
 *
 *  embedded brains GmbH
 *  Dornierstr. 4
 *  82178 Puchheim
 *  Germany
 *  <rtems@embedded-brains.de>
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rtems.org/license/LICENSE.
 */


#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <rtems/test-info.h>
#include <rtems.h>
#include <rtems/test.h>
#include <rtems/score/threadimpl.h>

static uint_fast32_t estimate_busy_loop_maximum( void )
{
  uint_fast32_t units = 0;
  uint_fast32_t initial = rtems_clock_get_ticks_since_boot();

  while ( initial == rtems_clock_get_ticks_since_boot() ) {
    ++units;
  }

  return units;
}

static uint_fast32_t wait_for_tick_change( void )
{
  uint_fast32_t initial = rtems_clock_get_ticks_since_boot();
  uint_fast32_t now;

  do {
    now = rtems_clock_get_ticks_since_boot();
  } while ( now == initial );

  return now;
}

uint_fast32_t rtems_test_get_one_tick_busy_count( void )
{
  uint_fast32_t last;
  uint_fast32_t now;
  uint_fast32_t a;
  uint_fast32_t b;
  uint_fast32_t m;

  /* Choose a lower bound */
  a = 1;

  /* Estimate an upper bound */

  wait_for_tick_change();
  b = 2 * estimate_busy_loop_maximum();

  while ( true ) {
    last = wait_for_tick_change();
    T_busy( b );
    now = rtems_clock_get_ticks_since_boot();

    if ( now != last ) {
      break;
    }

    b *= 2;
    last = now;
  }

  /* Find a good value */
  do {
    m = ( a + b ) / 2;

    last = wait_for_tick_change();
    T_busy( m );
    now = rtems_clock_get_ticks_since_boot();

    if ( now != last ) {
      b = m;
    } else {
      a = m;
    }
  } while ( b - a > 1 );

  return m;
}

void rtems_test_busy_cpu_usage( time_t seconds, long nanoseconds )
{
  Thread_Control    *executing;
  Timestamp_Control  busy;
  Timestamp_Control  start;
  Timestamp_Control  now;

  executing = _Thread_Get_executing();
  _Thread_Get_CPU_time_used( executing, &start );
  _Timestamp_Set( &busy, seconds, nanoseconds );

  do {
    _Thread_Get_CPU_time_used( executing, &now );
  } while ( now - start < busy );
}