File: timer.c

package info (click to toggle)
tcng 10b-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 3,632 kB
  • ctags: 2,515
  • sloc: ansic: 19,038; pascal: 4,640; yacc: 2,619; sh: 1,908; perl: 1,546; lex: 772; makefile: 755
file content (129 lines) | stat: -rw-r--r-- 2,698 bytes parent folder | download | duplicates (5)
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
122
123
124
125
126
127
128
129
/*
 * timer.c - Timer handling
 *
 * Written 2001 by Werner Almesberger
 * Copyright 2001 EPFL-ICA, Network Robots
 */


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <linux/sched.h> /* for HZ */

#include "tckernel.h"
#include "tcsim.h"
#include "jiffies.h"
#include "timer.h"


struct every {
   struct jiffval interval;
   struct timer_list timer;
   void *buffer;
   int len;
};

unsigned long jiffies = 0;	/* mirrors now.jiffies */
struct jiffval now = { 0, 0 };

static struct timer_list *timers = NULL;



static int timer_lt(const struct timer_list *a,const struct timer_list *b)
{
    if (a->expires < b->expires) return 1;
    if (a->expires > b->expires) return 0;
    return a->expires_ujiffies < b->expires_ujiffies;
}


static int timer_le(const struct timer_list *a,const struct timer_list *b)
{
    if (a->expires < b->expires) return 1;
    if (a->expires > b->expires) return 0;
    return a->expires_ujiffies <= b->expires_ujiffies;
}


void add_hires_timer(struct timer_list *timer)
{
    struct timer_list tmp = {
	.expires = now.jiffies,
	.expires_ujiffies = now.ujiffies,
    };
    struct timer_list **walk;

    if (debug)
	debugf("%ld.%06ld: adding timer %ld.%06ld (%p)",now.jiffies,
	  now.ujiffies,timer->expires,timer->expires_ujiffies,timer->function);
    if (timer_lt(timer,&tmp)) errorf("timer before current time");
    for (walk = &timers; *walk; walk = &(*walk)->next)
	if (!timer_le(*walk,timer)) break;
    timer->next = *walk;
    *walk = timer;
}


void add_timer(struct timer_list *timer)
{
    timer->expires_ujiffies = 0;
    add_hires_timer(timer);
}


int del_timer(struct timer_list *timer)
{
    struct timer_list **walk;

    for (walk = &timers; *walk && *walk != timer; walk = &(*walk)->next);
    if (!*walk) return 0;
    *walk = timer->next;
    return 1;
}


int mod_timer(struct timer_list *timer,unsigned long expires)
{
    int res;

    res = del_timer(timer);
    timer->expires = expires;
    timer->expires_ujiffies = 0;
    add_timer(timer);
    return res;
}


int advance_time(struct jiffval next)
{
    struct timer_list tmp = {
	.expires = next.jiffies,
	.expires_ujiffies = next.ujiffies,
    };

    if (jiffval_cmp(next,now) < 0) return -1;
    while (timers && timer_le(timers,&tmp)) {
	struct timer_list *this = timers;

	timers = timers->next;
	now.jiffies = jiffies = this->expires;
	now.ujiffies = this->expires_ujiffies;
	this->function(this->data);
	kernel_poll(NULL,0);
    }
    now = next;
    jiffies = now.jiffies;
    return 0;
}


void do_gettimeofday(struct timeval *tv)
{
    struct jiffval tmp = jtos(now);

    tv->tv_sec = tmp.jiffies;
    tv->tv_usec = tmp.ujiffies;
}