summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src/watchdogtick.c
blob: 2f11357019cde5a01eabc6955e6366d466a6e868 (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
111
112
113
114
115
116
117
/*
 * Copyright (c) 2015, 2016 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.
 */

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

#include <rtems/score/watchdogimpl.h>
#include <rtems/score/schedulerimpl.h>
#include <rtems/score/threaddispatch.h>
#include <rtems/score/timecounter.h>

void _Watchdog_Do_tickle(
  Watchdog_Header  *header,
  Watchdog_Control *first,
  uint64_t          now,
#ifdef RTEMS_SMP
  ISR_lock_Control *lock,
#endif
  ISR_lock_Context *lock_context
)
{
  do {
    if ( first->expire <= now ) {
      Watchdog_Service_routine_entry routine;

      _Watchdog_Next_first( header, first );
      _RBTree_Extract( &header->Watchdogs, &first->Node.RBTree );
      _Watchdog_Set_state( first, WATCHDOG_INACTIVE );
      routine = first->routine;

      _ISR_lock_Release_and_ISR_enable( lock, lock_context );
      ( *routine )( first );
      _ISR_lock_ISR_disable_and_acquire( lock, lock_context );
    } else {
      break;
    }

    first = _Watchdog_Header_first( header );
  } while ( first != NULL );
}

void _Watchdog_Tick( Per_CPU_Control *cpu )
{
  ISR_lock_Context  lock_context;
  Watchdog_Header  *header;
  Watchdog_Control *first;
  uint64_t          ticks;
  struct timespec   now;

  if ( _Per_CPU_Is_boot_processor( cpu ) ) {
    ++_Watchdog_Ticks_since_boot;
  }

  _ISR_lock_ISR_disable_and_acquire( &cpu->Watchdog.Lock, &lock_context );

  ticks = cpu->Watchdog.ticks;
  _Assert( ticks < UINT64_MAX );
  ++ticks;
  cpu->Watchdog.ticks = ticks;

  header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ];
  first = _Watchdog_Header_first( header );

  if ( first != NULL ) {
    _Watchdog_Tickle(
      header,
      first,
      ticks,
      &cpu->Watchdog.Lock,
      &lock_context
    );
  }

  header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_MONOTONIC ];
  first = _Watchdog_Header_first( header );

  if ( first != NULL ) {
    _Timecounter_Getnanouptime( &now );
    _Watchdog_Tickle(
      header,
      first,
      _Watchdog_Ticks_from_timespec( &now ),
      &cpu->Watchdog.Lock,
      &lock_context
    );
  }

  header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ];
  first = _Watchdog_Header_first( header );

  if ( first != NULL ) {
    _Timecounter_Getnanotime( &now );
    _Watchdog_Tickle(
      header,
      first,
      _Watchdog_Ticks_from_timespec( &now ),
      &cpu->Watchdog.Lock,
      &lock_context
    );
  }

  _ISR_lock_Release_and_ISR_enable( &cpu->Watchdog.Lock, &lock_context );

  _Scheduler_Tick( cpu );
}