File: timer.c

package info (click to toggle)
diald 0.16.5-2
  • links: PTS
  • area: main
  • in suites: hamm
  • size: 716 kB
  • ctags: 805
  • sloc: ansic: 5,438; tcl: 510; perl: 479; sh: 284; makefile: 166
file content (122 lines) | stat: -rw-r--r-- 2,819 bytes parent folder | download | duplicates (2)
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
/*
 * timer.c - This emulates the kernel timer routines in user space.
 *           Ugly, but it works.
 *
 * Copyright (c) 1994, 1995, 1996 Eric Schenk.
 * All rights reserved. Please see the file LICENSE which should be
 * distributed with this software for terms of use.
 */

#include "diald.h"

#include <signal.h>
#include <sys/time.h>
#include <sys/times.h>
#include <unistd.h>

static struct timer_lst head = {&head,&head,0,0,0,0};

/*
 * The following gets a time stamp based on the number of system
 * clock ticks since the system has been up.
 * Note that this measure of time is immune to changes in the
 * wall clock setting, and so we don't have to worry about the
 * wall clock getting mucked with.
 */

unsigned long timestamp()
{
   struct tms buf;
   return times(&buf)/CLK_TCK;
}

unsigned long ticks()
{
   struct tms buf;
   return times(&buf);
}

void init_timer(struct timer_lst * timer)
{
    timer->next = NULL;
    timer->prev = NULL;
}

/*
 * Basic idea: store time outs in order.
 * I'd be happier with a basic priority queue of some kind,
 * but this was the most direct way to code it, and it
 * matched the original kernel type definition I was using.
 */

void add_timer(struct timer_lst *timer)
{
    struct timer_lst *c;
    unsigned long atime;
    atime = timestamp();
    timer->expected = atime+timer->expires;
    c = head.next;
    /* march down the list looking for a home */
    while (c != &head) {
	if (timer->expected < c->expected) break;
	c = c->next;
    }

    timer->next = c;
    c->prev->next = timer;
    timer->prev = c->prev;
    c->prev = timer;
}

int del_timer(struct timer_lst *timer)
{
    unsigned long atime;
    atime = timestamp();
    /* return 0 if timer was not active */
    if (!timer->next) { return 0; }
    timer->next->prev = timer->prev;
    timer->prev->next = timer->next;
    timer->next = timer->prev = NULL;
    return 1;
}

int validate_function(struct timer_lst *c)
{
	if (c->function == (void*)del_impulse
	|| c->function == (void*)del_connection
	|| c->function == (void*)slip_start_fail)
		return 1;
	syslog(LOG_ERR, "Caught a bad function value %p. Tell Eric.\n",
		c->function);
	return 0;
}

void fire_timers()
{
    struct timer_lst *cn;
    struct timer_lst *c = head.next;
    unsigned long atime = timestamp();
    
    while (c != &head && c->expected <= atime) {
	c->next->prev = c->prev;
	c->prev->next = c->next;
	cn = c->next;
	c->next = c->prev = NULL;
	/* process the data, this may free the timer entry,
	 * so we can't refer to the contents of c again.
	 */
	if (validate_function(c))
		(*c->function)(c->data);
	c = cn;
    }
}

int next_alarm()
{
    unsigned long expires;
    if (head.next == &head)
	return 0;
    expires = head.next->expected - timestamp();
    if (expires < 0) expires = 0;
    return expires;
}