Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

file 121 lines (112 sloc) 2.895 kb
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 118 119 120 121
/* -----------------------------------------------------------------------------
*
* (c) The GHC Team, 1995-2005
*
* Interval timer service for profiling and pre-emptive scheduling.
*
* ---------------------------------------------------------------------------*/

/*
* The interval timer is used for profiling and for context switching in the
* threaded build.
*
* This file defines the platform-independent view of interval timing, relying
* on platform-specific services to install and run the timers.
*
*/
#include "Rts.h"
#include "RtsFlags.h"
#include "Proftimer.h"
#include "Storage.h"
#include "Schedule.h"
#include "Timer.h"
#include "Ticker.h"
#include "Capability.h"
#include "RtsSignals.h"

/* ticks left before next pre-emptive context switch */
static int ticks_to_ctxt_switch = 0;

#if defined(THREADED_RTS)
/* idle ticks left before we perform a GC */
static int ticks_to_gc = 0;
#endif

/*
* Function: handle_tick()
*
* At each occurrence of a tick, the OS timer will invoke
* handle_tick().
*/
static
void
handle_tick(int unused STG_UNUSED)
{
  handleProfTick();
  if (RtsFlags.ConcFlags.ctxtSwitchTicks > 0) {
      ticks_to_ctxt_switch--;
      if (ticks_to_ctxt_switch <= 0) {
ticks_to_ctxt_switch = RtsFlags.ConcFlags.ctxtSwitchTicks;
setContextSwitches(); /* schedule a context switch */
      }
  }

#if defined(THREADED_RTS)
  /*
* If we've been inactive for idleGCDelayTime (set by +RTS
* -I), tell the scheduler to wake up and do a GC, to check
* for threads that are deadlocked.
*/
  switch (recent_activity) {
  case ACTIVITY_YES:
      recent_activity = ACTIVITY_MAYBE_NO;
      ticks_to_gc = RtsFlags.GcFlags.idleGCDelayTime /
                    RtsFlags.MiscFlags.tickInterval;
      break;
  case ACTIVITY_MAYBE_NO:
      if (ticks_to_gc == 0) {
          /* 0 ==> no idle GC */
          recent_activity = ACTIVITY_DONE_GC;
          // disable timer signals (see #1623)
          stopTimer();
      } else {
          ticks_to_gc--;
          if (ticks_to_gc == 0) {
              ticks_to_gc = RtsFlags.GcFlags.idleGCDelayTime /
                  RtsFlags.MiscFlags.tickInterval;
              recent_activity = ACTIVITY_INACTIVE;
              blackholes_need_checking = rtsTrue;
              /* hack: re-use the blackholes_need_checking flag */
              wakeUpRts();
          }
      }
      break;
  default:
      break;
  }
#endif
}

void
initTimer(void)
{
    initProfTimer();
    if (RtsFlags.MiscFlags.tickInterval != 0) {
        initTicker(RtsFlags.MiscFlags.tickInterval, handle_tick);
    }
}

void
startTimer(void)
{
    if (RtsFlags.MiscFlags.tickInterval != 0) {
        startTicker();
    }
}

void
stopTimer(void)
{
    if (RtsFlags.MiscFlags.tickInterval != 0) {
        stopTicker();
    }
}

void
exitTimer(void)
{
    if (RtsFlags.MiscFlags.tickInterval != 0) {
        exitTicker();
    }
}
Something went wrong with that request. Please try again.