source: rtems/cpukit/include/rtems/score/smplockstats.h @ 21275b58

5
Last change on this file since 21275b58 was 5fc727f, checked in by Sebastian Huber <sebastian.huber@…>, on 11/26/18 at 07:25:36

score: <rtems/score/smplockstats.h>

Remove <rtems/score/chainimpl.h> include from
<rtems/score/smplockstats.h>.

Close #3598.

  • Property mode set to 100644
File size: 6.6 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreSMPLock
5 *
6 * @brief SMP Lock API
7 */
8
9/*
10 * Copyright (c) 2013, 2018 embedded brains GmbH
11 *
12 * The license and distribution terms for this file may be
13 * found in the file LICENSE in this distribution or at
14 * http://www.rtems.org/license/LICENSE.
15 */
16
17#ifndef _RTEMS_SCORE_SMPLOCKSTATS_H
18#define _RTEMS_SCORE_SMPLOCKSTATS_H
19
20#include <rtems/score/cpu.h>
21
22#if defined(RTEMS_SMP)
23
24#include <rtems/score/chain.h>
25
26#ifdef __cplusplus
27extern "C" {
28#endif /* __cplusplus */
29
30/**
31 * @addtogroup ScoreSMPLock
32 *
33 * @{
34 */
35
36#if defined(RTEMS_PROFILING)
37
38/**
39 * @brief Count of lock contention counters for lock statistics.
40 */
41#define SMP_LOCK_STATS_CONTENTION_COUNTS 4
42
43/**
44 * @brief SMP lock statistics.
45 *
46 * The lock acquire attempt instant is the point in time right after the
47 * interrupt disable action in the lock acquire sequence.
48 *
49 * The lock acquire instant is the point in time right after the lock
50 * acquisition.  This is the begin of the critical section code execution.
51 *
52 * The lock release instant is the point in time right before the interrupt
53 * enable action in the lock release sequence.
54 *
55 * The lock section time is the time elapsed between the lock acquire instant
56 * and the lock release instant.
57 *
58 * The lock acquire time is the time elapsed between the lock acquire attempt
59 * instant and the lock acquire instant.
60 */
61typedef struct {
62  /**
63   * @brief Node for SMP lock statistics chain.
64   */
65  Chain_Node Node;
66
67  /**
68   * @brief The maximum lock acquire time in CPU counter ticks.
69   */
70  CPU_Counter_ticks max_acquire_time;
71
72  /**
73   * @brief The maximum lock section time in CPU counter ticks.
74   */
75  CPU_Counter_ticks max_section_time;
76
77  /**
78   * @brief The count of lock uses.
79   *
80   * This value may overflow.
81   */
82  uint64_t usage_count;
83
84  /**
85   * @brief Total lock acquire time in nanoseconds.
86   *
87   * The average lock acquire time is the total acquire time divided by the
88   * lock usage count.  The ration of the total section and total acquire times
89   * gives a measure for the lock contention.
90   *
91   * This value may overflow.
92   */
93  uint64_t total_acquire_time;
94
95  /**
96   * @brief The counts of lock acquire operations by contention.
97   *
98   * The contention count for index N corresponds to a lock acquire attempt
99   * with an initial queue length of N.  The last index corresponds to all
100   * lock acquire attempts with an initial queue length greater than or equal
101   * to SMP_LOCK_STATS_CONTENTION_COUNTS minus one.
102   *
103   * The values may overflow.
104   */
105  uint64_t contention_counts[SMP_LOCK_STATS_CONTENTION_COUNTS];
106
107  /**
108   * @brief Total lock section time in CPU counter ticks.
109   *
110   * The average lock section time is the total section time divided by the
111   * lock usage count.
112   *
113   * This value may overflow.
114   */
115  uint64_t total_section_time;
116
117  /**
118   * @brief The lock name.
119   */
120  const char *name;
121} SMP_lock_Stats;
122
123/**
124 * @brief Local context for SMP lock statistics.
125 */
126typedef struct {
127  /**
128   * @brief The last lock acquire instant in CPU counter ticks.
129   *
130   * This value is used to measure the lock section time.
131   */
132  CPU_Counter_ticks acquire_instant;
133
134  /**
135   * @brief The lock stats used for the last lock acquire.
136   */
137  SMP_lock_Stats *stats;
138} SMP_lock_Stats_context;
139
140/**
141 * @brief SMP lock statistics initializer for static initialization.
142 */
143#define SMP_LOCK_STATS_INITIALIZER( name ) \
144  { { NULL, NULL }, 0, 0, 0, 0, { 0, 0, 0, 0 }, 0, name }
145
146/**
147 * @brief Initializes an SMP lock statistics block.
148 *
149 * @param[in, out] stats The SMP lock statistics block.
150 * @param[in] name The name for the SMP lock statistics.  This name must be
151 * persistent throughout the life time of this statistics block.
152 */
153static inline void _SMP_lock_Stats_initialize(
154  SMP_lock_Stats *stats,
155  const char *name
156)
157{
158  SMP_lock_Stats init = SMP_LOCK_STATS_INITIALIZER( name );
159
160  *stats = init;
161}
162
163/**
164 * @brief Destroys an SMP lock statistics block.
165 *
166 * @param[in] stats The SMP lock statistics block.
167 */
168void _SMP_lock_Stats_destroy( SMP_lock_Stats *stats );
169
170void _SMP_lock_Stats_register_or_max_section_time(
171  SMP_lock_Stats    *stats,
172  CPU_Counter_ticks  max_section_time
173);
174
175typedef struct {
176  CPU_Counter_ticks first;
177} SMP_lock_Stats_acquire_context;
178
179static inline void _SMP_lock_Stats_acquire_begin(
180  SMP_lock_Stats_acquire_context *acquire_context
181)
182{
183  acquire_context->first = _CPU_Counter_read();
184}
185
186static inline void _SMP_lock_Stats_acquire_end(
187  const SMP_lock_Stats_acquire_context *acquire_context,
188  SMP_lock_Stats                       *stats,
189  SMP_lock_Stats_context               *stats_context,
190  unsigned int                          queue_length
191)
192{
193  CPU_Counter_ticks second;
194  CPU_Counter_ticks delta;
195
196  second = _CPU_Counter_read();
197  stats_context->acquire_instant = second;
198  delta = _CPU_Counter_difference( second, acquire_context->first );
199
200  ++stats->usage_count;
201
202  stats->total_acquire_time += delta;
203
204  if ( stats->max_acquire_time < delta ) {
205    stats->max_acquire_time = delta;
206  }
207
208  if ( queue_length >= SMP_LOCK_STATS_CONTENTION_COUNTS ) {
209    queue_length = SMP_LOCK_STATS_CONTENTION_COUNTS - 1;
210  }
211  ++stats->contention_counts[ queue_length ];
212
213  stats_context->stats = stats;
214}
215
216/**
217 * @brief Updates an SMP lock statistics block during a lock release.
218 *
219 * @param[in] stats_context The SMP lock statistics context.
220 */
221static inline void _SMP_lock_Stats_release_update(
222  const SMP_lock_Stats_context *stats_context
223)
224{
225  SMP_lock_Stats    *stats;
226  CPU_Counter_ticks  first;
227  CPU_Counter_ticks  second;
228  CPU_Counter_ticks  delta;
229
230  stats = stats_context->stats;
231  first = stats_context->acquire_instant;
232  second = _CPU_Counter_read();
233  delta = _CPU_Counter_difference( second, first );
234
235  stats->total_section_time += delta;
236
237  if ( stats->max_section_time < delta ) {
238    _SMP_lock_Stats_register_or_max_section_time( stats, delta );
239  }
240}
241
242typedef struct {
243  Chain_Node Node;
244  SMP_lock_Stats *current;
245} SMP_lock_Stats_iteration_context;
246
247void _SMP_lock_Stats_iteration_start(
248  SMP_lock_Stats_iteration_context *iteration_context
249);
250
251
252bool _SMP_lock_Stats_iteration_next(
253  SMP_lock_Stats_iteration_context *iteration_context,
254  SMP_lock_Stats                   *snapshot,
255  char                             *name,
256  size_t                            name_size
257);
258
259void _SMP_lock_Stats_iteration_stop(
260  SMP_lock_Stats_iteration_context *iteration_context
261);
262
263#else /* RTEMS_PROFILING */
264
265#define _SMP_lock_Stats_initialize( stats, name ) do { } while ( 0 )
266
267#define _SMP_lock_Stats_destroy( stats ) do { } while ( 0 )
268
269#endif /* !RTEMS_PROFILING */
270
271/**@}*/
272
273#ifdef __cplusplus
274}
275#endif /* __cplusplus */
276
277#endif /* RTEMS_SMP */
278
279#endif /* _RTEMS_SCORE_SMPLOCKSTATS_H */
Note: See TracBrowser for help on using the repository browser.