summaryrefslogtreecommitdiffstats
path: root/cpukit/posix/src/timertsr.c
blob: 85554633e92268d666a86995e61168f5f846cd68 (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
/**
 * @file
 *
 * @brief Operation that is run when a timer expires
 * @ingroup POSIX_INTERNAL_TIMERS Timers
 */

/*
 * _POSIX_Timer_TSR
 *
 *  COPYRIGHT (c) 1989-2007.
 *  On-Line Applications Research Corporation (OAR).
 *
 *  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 <time.h>
#include <pthread.h>
#include <signal.h>

#include <rtems/posix/time.h>
#include <rtems/posix/ptimer.h>
#include <rtems/posix/timerimpl.h>
#include <rtems/score/todimpl.h>

/*
 *  This is the operation that is run when a timer expires
 */
void _POSIX_Timer_TSR(
  Objects_Id timer __attribute__((unused)),
  void *data)
{
  POSIX_Timer_Control *ptimer;
  bool                 activated;

  ptimer = (POSIX_Timer_Control *)data;

  /* Increment the number of expirations. */
  ptimer->overrun = ptimer->overrun + 1;

  /* The timer must be reprogrammed */
  if ( ( ptimer->timer_data.it_interval.tv_sec  != 0 ) ||
       ( ptimer->timer_data.it_interval.tv_nsec != 0 ) ) {
    activated = _POSIX_Timer_Insert_helper(
      &ptimer->Timer,
      ptimer->ticks,
      ptimer->Object.id,
      _POSIX_Timer_TSR,
      ptimer
    );
    if ( !activated )
      return;

    /* Store the time when the timer was started again */
    _TOD_Get( &ptimer->time );

    /* The state really did not change but just to be safe */
    ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
  } else {
   /* Indicates that the timer is stopped */
   ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
  }

  /*
   * The sending of the signal to the process running the handling function
   * specified for that signal is simulated
   */

  if ( pthread_kill ( ptimer->thread_id, ptimer->inf.sigev_signo ) ) {
    _Assert( FALSE );
    /*
     * TODO: What if an error happens at run-time? This should never
     *       occur because the timer should be canceled if the thread
     *       is deleted. This method is being invoked from the Clock
     *       Tick ISR so even if we decide to take action on an error,
     *       we don't have many options. We shouldn't shut the system down.
     */
  }

  /* After the signal handler returns, the count of expirations of the
   * timer must be set to 0.
   */
  ptimer->overrun = 0;
}