static void test_timeout(unsigned long data)
{
  do_gettimeofday_fast(&tv_exp[data]);
  exp_num[data] = num_test_timeout;

  num_test_timeout++;
}
Exemple #2
0
/* In version 1.4 this function takes 27 - 50 us */
void start_one_shot_timer(struct fast_timer *t,
                          fast_timer_function_type *function,
                          unsigned long data,
                          unsigned long delay_us,
                          const char *name)
{
  unsigned long flags;
  struct fast_timer *tmp;

  D1(printk("sft %s %d us\n", name, delay_us));

  local_irq_save(flags);

  do_gettimeofday_fast(&t->tv_set);
  tmp = fast_timer_list;

  SANITYCHECK({ /* Check so this is not in the list already... */
    while (tmp != NULL)
    {
      if (tmp == t)
      {
        printk("timer name: %s data: 0x%08lX already in list!\n", name, data);
        sanity_failed++;
        return;
      }
      else
      {
        tmp = tmp->next;
      }
    }
    tmp = fast_timer_list;
  });
static void test_timeout1(unsigned long data)
{
  do_gettimeofday_fast(&tv_exp[data]);
  exp_num[data] = num_test_timeout;
  if (data < 7)
  {
    start_one_shot_timer(&tr[i], test_timeout1, i, 1000, "timeout1");
    i++;
  }
  num_test_timeout++;
}
static int proc_fasttimer_show(struct seq_file *m, void *v)
{
	unsigned long flags;
	int i = 0;
	int num_to_show;
	struct fasttime_t tv;
	struct fast_timer *t, *nextt;

	do_gettimeofday_fast(&tv);

	seq_printf(m, "Fast timers added:     %i\n", fast_timers_added);
	seq_printf(m, "Fast timers started:   %i\n", fast_timers_started);
	seq_printf(m, "Fast timer interrupts: %i\n", fast_timer_ints);
	seq_printf(m, "Fast timers expired:   %i\n", fast_timers_expired);
	seq_printf(m, "Fast timers deleted:   %i\n", fast_timers_deleted);
	seq_printf(m, "Fast timer running:    %s\n",
		   fast_timer_running ? "yes" : "no");
	seq_printf(m, "Current time:          %lu.%06lu\n",
		   (unsigned long)tv.tv_jiff,
		   (unsigned long)tv.tv_usec);
#ifdef FAST_TIMER_SANITY_CHECKS
	seq_printf(m, "Sanity failed:         %i\n", sanity_failed);
#endif
	seq_putc(m, '\n');

#ifdef DEBUG_LOG_INCLUDED
	{
		int end_i = debug_log_cnt;
		i = 0;

		if (debug_log_cnt_wrapped)
			i = debug_log_cnt;

		while ((i != end_i || debug_log_cnt_wrapped)) {
			seq_printf(m, debug_log_string[i], debug_log_value[i]);
			if (seq_has_overflowed(m))
				return 0;
			i = (i+1) % DEBUG_LOG_MAX;
		}
	}
	seq_putc(m, '\n');
#endif

	num_to_show = (fast_timers_started < NUM_TIMER_STATS ? fast_timers_started:
		       NUM_TIMER_STATS);
	seq_printf(m, "Timers started: %i\n", fast_timers_started);
	for (i = 0; i < num_to_show; i++) {
		int cur = (fast_timers_started - i - 1) % NUM_TIMER_STATS;

#if 1 //ndef FAST_TIMER_LOG
		seq_printf(m, "div: %i delay: %i\n",
			   timer_div_settings[cur],
			   timer_delay_settings[cur]);
#endif
#ifdef FAST_TIMER_LOG
		t = &timer_started_log[cur];
		seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n",
			   t->name,
			   (unsigned long)t->tv_set.tv_jiff,
			   (unsigned long)t->tv_set.tv_usec,
			   (unsigned long)t->tv_expires.tv_jiff,
			   (unsigned long)t->tv_expires.tv_usec,
			   t->delay_us,
			   t->data);
		if (seq_has_overflowed(m))
			return 0;
#endif
	}
	seq_putc(m, '\n');

#ifdef FAST_TIMER_LOG
	num_to_show = (fast_timers_added < NUM_TIMER_STATS ? fast_timers_added:
		       NUM_TIMER_STATS);
	seq_printf(m, "Timers added: %i\n", fast_timers_added);
	for (i = 0; i < num_to_show; i++) {
		t = &timer_added_log[(fast_timers_added - i - 1) % NUM_TIMER_STATS];
		seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n",
			   t->name,
			   (unsigned long)t->tv_set.tv_jiff,
			   (unsigned long)t->tv_set.tv_usec,
			   (unsigned long)t->tv_expires.tv_jiff,
			   (unsigned long)t->tv_expires.tv_usec,
			   t->delay_us,
			   t->data);
		if (seq_has_overflowed(m))
			return 0;
	}
	seq_putc(m, '\n');

	num_to_show = (fast_timers_expired < NUM_TIMER_STATS ? fast_timers_expired:
		       NUM_TIMER_STATS);
	seq_printf(m, "Timers expired: %i\n", fast_timers_expired);
	for (i = 0; i < num_to_show; i++){
		t = &timer_expired_log[(fast_timers_expired - i - 1) % NUM_TIMER_STATS];
		seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n",
			   t->name,
			   (unsigned long)t->tv_set.tv_jiff,
			   (unsigned long)t->tv_set.tv_usec,
			   (unsigned long)t->tv_expires.tv_jiff,
			   (unsigned long)t->tv_expires.tv_usec,
			   t->delay_us,
			   t->data);
		if (seq_has_overflowed(m))
			return 0;
	}
	seq_putc(m, '\n');
#endif

	seq_puts(m, "Active timers:\n");
	local_irq_save(flags);
	t = fast_timer_list;
	while (t != NULL){
		nextt = t->next;
		local_irq_restore(flags);
		seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n",
			   t->name,
			   (unsigned long)t->tv_set.tv_jiff,
			   (unsigned long)t->tv_set.tv_usec,
			   (unsigned long)t->tv_expires.tv_jiff,
			   (unsigned long)t->tv_expires.tv_usec,
			   t->delay_us,
			   t->data);
		if (seq_has_overflowed(m))
			return 0;
		local_irq_save(flags);
		if (t->next != nextt)
			printk("timer removed!\n");
		t = nextt;
	}
	local_irq_restore(flags);
	return 0;
}
/* In version 1.4 this function takes 27 - 50 us */
void start_one_shot_timer(struct fast_timer *t,
                          fast_timer_function_type *function,
                          unsigned long data,
                          unsigned long delay_us,
                          const char *name)
{
  unsigned long flags;
  struct fast_timer *tmp;

  D1(printk("sft %s %d us\n", name, delay_us));

  local_irq_save(flags);

  do_gettimeofday_fast(&t->tv_set);
  tmp = fast_timer_list;

#ifdef FAST_TIMER_SANITY_CHECKS
	/* Check so this is not in the list already... */
	while (tmp != NULL) {
		if (tmp == t) {
			printk(KERN_DEBUG
				"timer name: %s data: 0x%08lX already "
				"in list!\n", name, data);
			sanity_failed++;
			goto done;
		} else
			tmp = tmp->next;
	}
	tmp = fast_timer_list;
#endif

  t->delay_us = delay_us;
  t->function = function;
  t->data = data;
  t->name = name;

  t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000;
	t->tv_expires.tv_jiff = t->tv_set.tv_jiff + delay_us / 1000000 / HZ;
	if (t->tv_expires.tv_usec > 1000000) {
    t->tv_expires.tv_usec -= 1000000;
		t->tv_expires.tv_jiff += HZ;
  }
#ifdef FAST_TIMER_LOG
  timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t;
#endif
  fast_timers_added++;

  /* Check if this should timeout before anything else */
  if (tmp == NULL || fasttime_cmp(&t->tv_expires, &tmp->tv_expires) < 0) {
    /* Put first in list and modify the timer value */
    t->prev = NULL;
    t->next = fast_timer_list;
    if (fast_timer_list)
      fast_timer_list->prev = t;
    fast_timer_list = t;
#ifdef FAST_TIMER_LOG
    timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
#endif
    start_timer_trig(delay_us);
  } else {
    /* Put in correct place in list */
    while (tmp->next &&
        fasttime_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0)
      tmp = tmp->next;
    /* Insert t after tmp */
    t->prev = tmp;
    t->next = tmp->next;
    if (tmp->next)
    {
      tmp->next->prev = t;
    }
    tmp->next = t;
  }

  D2(printk("start_one_shot_timer: %d us done\n", delay_us));

done:
  local_irq_restore(flags);
} /* start_one_shot_timer */
static void timer_trig_handler(struct work_struct *work)
{
	reg_timer_rw_ack_intr ack_intr = { 0 };
	reg_timer_rw_intr_mask intr_mask;
	reg_timer_rw_trig_cfg trig_cfg = { 0 };
	struct fast_timer *t;
	fast_timer_function_type *f;
	unsigned long d;
	unsigned long flags;

	/* We keep interrupts disabled not only when we modify the
	 * fast timer list, but any time we hold a reference to a
	 * timer in the list, since del_fast_timer may be called
	 * from (another) interrupt context.  Thus, the only time
	 * when interrupts are enabled is when calling the timer
	 * callback function.
	 */
  local_irq_save(flags);

  /* Clear timer trig interrupt */
	intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask);
  intr_mask.trig = 0;
  REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask);

  /* First stop timer, then ack interrupt */
  /* Stop timer */
  trig_cfg.tmr = regk_timer_off;
	REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg);

  /* Ack interrupt */
  ack_intr.trig = 1;
	REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr);

  fast_timer_running = 0;
  fast_timer_ints++;

  t = fast_timer_list;
	while (t) {
		struct fasttime_t tv;

    /* Has it really expired? */
    do_gettimeofday_fast(&tv);
		D1(printk(KERN_DEBUG
			"t: %is %06ius\n", tv.tv_jiff, tv.tv_usec));

		if (fasttime_cmp(&t->tv_expires, &tv) <= 0) {
      /* Yes it has expired */
#ifdef FAST_TIMER_LOG
      timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t;
#endif
      fast_timers_expired++;

      /* Remove this timer before call, since it may reuse the timer */
      if (t->prev)
        t->prev->next = t->next;
      else
        fast_timer_list = t->next;
      if (t->next)
        t->next->prev = t->prev;
      t->prev = NULL;
      t->next = NULL;

			/* Save function callback data before enabling
			 * interrupts, since the timer may be removed and we
			 * don't know how it was allocated (e.g. ->function
			 * and ->data may become overwritten after deletion
			 * if the timer was stack-allocated).
			 */
			f = t->function;
			d = t->data;

			if (f != NULL) {
				/* Run the callback function with interrupts
				 * enabled. */
				local_irq_restore(flags);
				f(d);
				local_irq_save(flags);
			} else
        DEBUG_LOG("!trimertrig %i function==NULL!\n", fast_timer_ints);
		} else {
      /* Timer is to early, let's set it again using the normal routines */
      D1(printk(".\n"));
    }

		t = fast_timer_list;
		if (t != NULL) {
      /* Start next timer.. */
			long us = 0;
			struct fasttime_t tv;

      do_gettimeofday_fast(&tv);

			/* time_after_eq takes care of wrapping */
			if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff))
				us = ((t->tv_expires.tv_jiff - tv.tv_jiff) *
					1000000 / HZ + t->tv_expires.tv_usec -
					tv.tv_usec);

			if (us > 0) {
				if (!fast_timer_running) {
#ifdef FAST_TIMER_LOG
          timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
#endif
          start_timer_trig(us);
        }
        break;
			} else {
        /* Timer already expired, let's handle it better late than never.
         * The normal loop handles it
         */
        D1(printk("e! %d\n", us));
      }
    }
  }

	local_irq_restore(flags);

	if (!t)
    D1(printk("ttrig stop!\n"));
}
static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
                       ,int *eof, void *data_unused)
{
  unsigned long flags;
  int i = 0;
  int num_to_show;
	struct fasttime_t tv;
  struct fast_timer *t, *nextt;
  static char *bigbuf = NULL;
  static unsigned long used;

	if (!bigbuf) {
		bigbuf = vmalloc(BIG_BUF_SIZE);
		if (!bigbuf) {
			used = 0;
			if (buf)
				buf[0] = '\0';
			return 0;
		}
	}

	if (!offset || !used) {
    do_gettimeofday_fast(&tv);

    used = 0;
    used += sprintf(bigbuf + used, "Fast timers added:     %i\n",
                    fast_timers_added);
    used += sprintf(bigbuf + used, "Fast timers started:   %i\n",
                    fast_timers_started);
    used += sprintf(bigbuf + used, "Fast timer interrupts: %i\n",
                    fast_timer_ints);
    used += sprintf(bigbuf + used, "Fast timers expired:   %i\n",
                    fast_timers_expired);
    used += sprintf(bigbuf + used, "Fast timers deleted:   %i\n",
                    fast_timers_deleted);
    used += sprintf(bigbuf + used, "Fast timer running:    %s\n",
                    fast_timer_running ? "yes" : "no");
    used += sprintf(bigbuf + used, "Current time:          %lu.%06lu\n",
			(unsigned long)tv.tv_jiff,
                    (unsigned long)tv.tv_usec);
#ifdef FAST_TIMER_SANITY_CHECKS
    used += sprintf(bigbuf + used, "Sanity failed:         %i\n",
                    sanity_failed);
#endif
    used += sprintf(bigbuf + used, "\n");

#ifdef DEBUG_LOG_INCLUDED
    {
      int end_i = debug_log_cnt;
      i = 0;

			if (debug_log_cnt_wrapped)
        i = debug_log_cnt;

      while ((i != end_i || (debug_log_cnt_wrapped && !used)) &&
             used+100 < BIG_BUF_SIZE)
      {
        used += sprintf(bigbuf + used, debug_log_string[i],
                        debug_log_value[i]);
        i = (i+1) % DEBUG_LOG_MAX;
      }
    }
    used += sprintf(bigbuf + used, "\n");
#endif

    num_to_show = (fast_timers_started < NUM_TIMER_STATS ? fast_timers_started:
                   NUM_TIMER_STATS);
    used += sprintf(bigbuf + used, "Timers started: %i\n", fast_timers_started);
    for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE) ; i++)
    {
      int cur = (fast_timers_started - i - 1) % NUM_TIMER_STATS;

#if 1 //ndef FAST_TIMER_LOG
      used += sprintf(bigbuf + used, "div: %i delay: %i"
                      "\n",
                      timer_div_settings[cur],
                      timer_delay_settings[cur]
                      );
#endif
#ifdef FAST_TIMER_LOG
      t = &timer_started_log[cur];
      used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
                      "d: %6li us data: 0x%08lX"
                      "\n",
                      t->name,
				(unsigned long)t->tv_set.tv_jiff,
                      (unsigned long)t->tv_set.tv_usec,
				(unsigned long)t->tv_expires.tv_jiff,
                      (unsigned long)t->tv_expires.tv_usec,
                      t->delay_us,
                      t->data
                      );
#endif
    }
    used += sprintf(bigbuf + used, "\n");

#ifdef FAST_TIMER_LOG
    num_to_show = (fast_timers_added < NUM_TIMER_STATS ? fast_timers_added:
                   NUM_TIMER_STATS);
    used += sprintf(bigbuf + used, "Timers added: %i\n", fast_timers_added);
    for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE); i++)
    {
      t = &timer_added_log[(fast_timers_added - i - 1) % NUM_TIMER_STATS];
      used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
                      "d: %6li us data: 0x%08lX"
                      "\n",
                      t->name,
				(unsigned long)t->tv_set.tv_jiff,
                      (unsigned long)t->tv_set.tv_usec,
				(unsigned long)t->tv_expires.tv_jiff,
                      (unsigned long)t->tv_expires.tv_usec,
                      t->delay_us,
                      t->data
                      );
    }
    used += sprintf(bigbuf + used, "\n");

    num_to_show = (fast_timers_expired < NUM_TIMER_STATS ? fast_timers_expired:
                   NUM_TIMER_STATS);
    used += sprintf(bigbuf + used, "Timers expired: %i\n", fast_timers_expired);
    for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE); i++)
    {
      t = &timer_expired_log[(fast_timers_expired - i - 1) % NUM_TIMER_STATS];
      used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
                      "d: %6li us data: 0x%08lX"
                      "\n",
                      t->name,
				(unsigned long)t->tv_set.tv_jiff,
                      (unsigned long)t->tv_set.tv_usec,
				(unsigned long)t->tv_expires.tv_jiff,
                      (unsigned long)t->tv_expires.tv_usec,
                      t->delay_us,
                      t->data
                      );
    }
    used += sprintf(bigbuf + used, "\n");
#endif

    used += sprintf(bigbuf + used, "Active timers:\n");
    local_irq_save(flags);
    t = fast_timer_list;
    while (t != NULL && (used+100 < BIG_BUF_SIZE))
    {
      nextt = t->next;
      local_irq_restore(flags);
      used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
			"d: %6li us data: 0x%08lX"
/*			" func: 0x%08lX" */
			"\n",
			t->name,
			(unsigned long)t->tv_set.tv_jiff,
			(unsigned long)t->tv_set.tv_usec,
			(unsigned long)t->tv_expires.tv_jiff,
			(unsigned long)t->tv_expires.tv_usec,
                      t->delay_us,
                      t->data
/*                      , t->function */
                      );
			local_irq_save(flags);
      if (t->next != nextt)
      {
        printk("timer removed!\n");
      }
      t = nextt;
    }
    local_irq_restore(flags);
  }

  if (used - offset < len)
  {
    len = used - offset;
  }

  memcpy(buf, bigbuf + offset, len);
  *start = buf;
  *eof = 1;

  return len;
}
Exemple #8
0
static irqreturn_t
timer1_handler(int irq, void *dev_id)
{
  struct fast_timer *t;
  unsigned long flags;

	/* We keep interrupts disabled not only when we modify the
	 * fast timer list, but any time we hold a reference to a
	 * timer in the list, since del_fast_timer may be called
	 * from (another) interrupt context.  Thus, the only time
	 * when interrupts are enabled is when calling the timer
	 * callback function.
	 */
  local_irq_save(flags);

  /* Clear timer1 irq */
  *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);

  /* First stop timer, then ack interrupt */
  /* Stop timer */
  *R_TIMER_CTRL = r_timer_ctrl_shadow =
    (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
    IO_STATE(R_TIMER_CTRL, tm1, stop_ld);

  /* Ack interrupt */
  *R_TIMER_CTRL =  r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i1, clr);

  fast_timer_running = 0;
  fast_timer_ints++;

  t = fast_timer_list;
  while (t)
  {
		struct fasttime_t tv;
		fast_timer_function_type *f;
		unsigned long d;

    /* Has it really expired? */
    do_gettimeofday_fast(&tv);
		D1(printk(KERN_DEBUG "t: %is %06ius\n",
			tv.tv_jiff, tv.tv_usec));

		if (fasttime_cmp(&t->tv_expires, &tv) <= 0)
    {
      /* Yes it has expired */
#ifdef FAST_TIMER_LOG
      timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t;
#endif
      fast_timers_expired++;

      /* Remove this timer before call, since it may reuse the timer */
      if (t->prev)
      {
        t->prev->next = t->next;
      }
      else
      {
        fast_timer_list = t->next;
      }
      if (t->next)
      {
        t->next->prev = t->prev;
      }
      t->prev = NULL;
      t->next = NULL;

			/* Save function callback data before enabling
			 * interrupts, since the timer may be removed and
			 * we don't know how it was allocated
			 * (e.g. ->function and ->data may become overwritten
			 * after deletion if the timer was stack-allocated).
			 */
			f = t->function;
			d = t->data;

			if (f != NULL) {
				/* Run callback with interrupts enabled. */
				local_irq_restore(flags);
				f(d);
				local_irq_save(flags);
			} else
        DEBUG_LOG("!timer1 %i function==NULL!\n", fast_timer_ints);
    }
    else
    {
      /* Timer is to early, let's set it again using the normal routines */
      D1(printk(".\n"));
    }

    if ((t = fast_timer_list) != NULL)
    {
      /* Start next timer.. */
			long us = 0;
			struct fasttime_t tv;

      do_gettimeofday_fast(&tv);

			/* time_after_eq takes care of wrapping */
			if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff))
				us = ((t->tv_expires.tv_jiff - tv.tv_jiff) *
					1000000 / HZ + t->tv_expires.tv_usec -
					tv.tv_usec);

      if (us > 0)
      {
        if (!fast_timer_running)
        {
#ifdef FAST_TIMER_LOG
          timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
#endif
          start_timer1(us);
        }
        break;
      }
      else
      {
        /* Timer already expired, let's handle it better late than never.
         * The normal loop handles it
         */
        D1(printk("e! %d\n", us));
      }
    }
  }

	local_irq_restore(flags);

  if (!t)
  {
    D1(printk("t1 stop!\n"));
  }

  return IRQ_HANDLED;
}
static irqreturn_t
timer1_handler(int irq, void *dev_id)
{
  struct fast_timer *t;
  unsigned long flags;

	/*                                                        
                                                          
                                                         
                                                          
                                                         
                      
  */
  local_irq_save(flags);

  /*                  */
  *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);

  /*                                      */
  /*            */
  *R_TIMER_CTRL = r_timer_ctrl_shadow =
    (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
    IO_STATE(R_TIMER_CTRL, tm1, stop_ld);

  /*               */
  *R_TIMER_CTRL =  r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i1, clr);

  fast_timer_running = 0;
  fast_timer_ints++;

  t = fast_timer_list;
  while (t)
  {
		struct fasttime_t tv;
		fast_timer_function_type *f;
		unsigned long d;

    /*                        */
    do_gettimeofday_fast(&tv);
		D1(printk(KERN_DEBUG "t: %is %06ius\n",
			tv.tv_jiff, tv.tv_usec));

		if (fasttime_cmp(&t->tv_expires, &tv) <= 0)
    {
      /*                    */
#ifdef FAST_TIMER_LOG
      timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t;
#endif
      fast_timers_expired++;

      /*                                                             */
      if (t->prev)
      {
        t->prev->next = t->next;
      }
      else
      {
        fast_timer_list = t->next;
      }
      if (t->next)
      {
        t->next->prev = t->prev;
      }
      t->prev = NULL;
      t->next = NULL;

			/*                                            
                                                    
                                        
                                                        
                                                       
    */
			f = t->function;
			d = t->data;

			if (f != NULL) {
				/*                                       */
				local_irq_restore(flags);
				f(d);
				local_irq_save(flags);
			} else
        DEBUG_LOG("!timer1 %i function==NULL!\n", fast_timer_ints);
    }
    else
    {
      /*                                                                 */
      D1(printk(".\n"));
    }

    if ((t = fast_timer_list) != NULL)
    {
      /*                    */
			long us = 0;
			struct fasttime_t tv;

      do_gettimeofday_fast(&tv);

			/*                                      */
			if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff))
				us = ((t->tv_expires.tv_jiff - tv.tv_jiff) *
					1000000 / HZ + t->tv_expires.tv_usec -
					tv.tv_usec);

      if (us > 0)
      {
        if (!fast_timer_running)
        {
#ifdef FAST_TIMER_LOG
          timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
#endif
          start_timer1(us);
        }
        break;
      }
      else
      {
        /*                                                               
                                     
         */
        D1(printk("e! %d\n", us));
      }
    }
  }

	local_irq_restore(flags);

  if (!t)
  {
    D1(printk("t1 stop!\n"));
  }

  return IRQ_HANDLED;
}
void start_one_shot_timer(struct fast_timer *t,
                          fast_timer_function_type *function,
                          unsigned long data,
                          unsigned long delay_us,
                          const char *name)
{
  unsigned long flags;
  struct fast_timer *tmp;

  D1(printk("sft %s %d us\n", name, delay_us));

  local_irq_save(flags);

  do_gettimeofday_fast(&t->tv_set);
  tmp = fast_timer_list;

#ifdef FAST_TIMER_SANITY_CHECKS
	/*                                             */
	while (tmp != NULL) {
		if (tmp == t) {
			printk(KERN_WARNING "timer name: %s data: "
				"0x%08lX already in list!\n", name, data);
			sanity_failed++;
			goto done;
		} else
			tmp = tmp->next;
	}
	tmp = fast_timer_list;
#endif

  t->delay_us = delay_us;
  t->function = function;
  t->data = data;
  t->name = name;

  t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000;
	t->tv_expires.tv_jiff = t->tv_set.tv_jiff + delay_us / 1000000 / HZ;
  if (t->tv_expires.tv_usec > 1000000)
  {
    t->tv_expires.tv_usec -= 1000000;
		t->tv_expires.tv_jiff += HZ;
  }
#ifdef FAST_TIMER_LOG
  timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t;
#endif
  fast_timers_added++;

  /*                                                   */
	if (tmp == NULL || fasttime_cmp(&t->tv_expires, &tmp->tv_expires) < 0)
  {
    /*                                              */
    t->prev = NULL;
    t->next = fast_timer_list;
    if (fast_timer_list)
    {
      fast_timer_list->prev = t;
    }
    fast_timer_list = t;
#ifdef FAST_TIMER_LOG
    timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
#endif
    start_timer1(delay_us);
  } else {
    /*                              */
		while (tmp->next && fasttime_cmp(&t->tv_expires,
				&tmp->next->tv_expires) > 0)
    {
      tmp = tmp->next;
    }
    /*                    */
    t->prev = tmp;
    t->next = tmp->next;
    if (tmp->next)
    {
      tmp->next->prev = t;
    }
    tmp->next = t;
  }

  D2(printk("start_one_shot_timer: %d us done\n", delay_us));

done:
  local_irq_restore(flags);
} /*                      */
Exemple #11
0
static irqreturn_t
timer1_handler(int irq, void *dev_id)
{
  struct fast_timer *t;
  unsigned long flags;

  local_irq_save(flags);

  
  *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);

  
  
  *R_TIMER_CTRL = r_timer_ctrl_shadow =
    (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
    IO_STATE(R_TIMER_CTRL, tm1, stop_ld);

  
  *R_TIMER_CTRL =  r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i1, clr);

  fast_timer_running = 0;
  fast_timer_ints++;

  t = fast_timer_list;
  while (t)
  {
		struct fasttime_t tv;
		fast_timer_function_type *f;
		unsigned long d;

    
    do_gettimeofday_fast(&tv);
		D1(printk(KERN_DEBUG "t: %is %06ius\n",
			tv.tv_jiff, tv.tv_usec));

		if (fasttime_cmp(&t->tv_expires, &tv) <= 0)
    {
      
#ifdef FAST_TIMER_LOG
      timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t;
#endif
      fast_timers_expired++;

      
      if (t->prev)
      {
        t->prev->next = t->next;
      }
      else
      {
        fast_timer_list = t->next;
      }
      if (t->next)
      {
        t->next->prev = t->prev;
      }
      t->prev = NULL;
      t->next = NULL;

			/* Save function callback data before enabling
			 * interrupts, since the timer may be removed and
			 * we don't know how it was allocated
			 * (e.g. ->function and ->data may become overwritten
			 * after deletion if the timer was stack-allocated).
			 */
			f = t->function;
			d = t->data;

			if (f != NULL) {
				
				local_irq_restore(flags);
				f(d);
				local_irq_save(flags);
			} else
        DEBUG_LOG("!timer1 %i function==NULL!\n", fast_timer_ints);
    }
    else
    {
      
      D1(printk(".\n"));
    }

    if ((t = fast_timer_list) != NULL)
    {
      
			long us = 0;
			struct fasttime_t tv;

      do_gettimeofday_fast(&tv);

			
			if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff))
				us = ((t->tv_expires.tv_jiff - tv.tv_jiff) *
					1000000 / HZ + t->tv_expires.tv_usec -
					tv.tv_usec);

      if (us > 0)
      {
        if (!fast_timer_running)
        {
#ifdef FAST_TIMER_LOG
          timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
#endif
          start_timer1(us);
        }
        break;
      }
      else
      {
        D1(printk("e! %d\n", us));
      }
    }
  }

	local_irq_restore(flags);

  if (!t)
  {
    D1(printk("t1 stop!\n"));
  }

  return IRQ_HANDLED;
}