-
Notifications
You must be signed in to change notification settings - Fork 0
/
timeoutq.c
173 lines (148 loc) · 3.09 KB
/
timeoutq.c
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//
// timeout queue
//
#include "os.h"
#include "llist.h"
#include "time.h"
struct event {
LL_PTRS;
int timeout;
int repeat_interval;
pfv_t go;
unsigned int data;
};
#define MAX_EVENTS 8
struct event queue[ MAX_EVENTS ];
// list anchors -- important, but ignore them; they are never used directly
llobject_t TQ;
llobject_t FL;
struct event *timeoutq;
struct event *freelist;
unsigned int then_usec;
unsigned int now_usec( void )
{
unsigned int us;
us=gettime(); //from "time.h"
return us;
}
// sets up concept of local time
// initializes the timeoutq and freelist
// fills the freelist with entries
// timeoutq is empty
//
void
init_timeoutq()
{
int i;
then_usec = now_usec();
timeoutq = (struct event *)&TQ;
LL_INIT(timeoutq);
freelist = (struct event *)&FL;
LL_INIT(freelist);
for (i=0; i<MAX_EVENTS; i++) {
struct event *ep = &queue[i];
LL_PUSH(freelist, ep);
}
return;
}
//
// account for however much time has elapsed since last update
// return timeout or MAX
//
int
bring_timeoutq_current()
{
unsigned int now;
struct event *ep;
ep = (struct event *)LL_HEAD(timeoutq); //ep now points to the head of TimeoutQ
if(!LL_IS_EMPTY(ep))
{
now = now_usec();
ep->timeout -= (now-then_usec);
return (ep->timeout);
}
else
return 0;
}
//
// get a new event structure from the freelist,
// initialize it, and insert it into the timeoutq
//
void
create_timeoutq_event(int timeout, int repeat, pfv_t function, unsigned int data)
{
struct event *x;
struct event *tempptr;
x = (struct event*)LL_POP(freelist);
x->timeout = timeout;
x->repeat_interval = repeat;
x->go = function;
x->data = data;
if(LL_IS_EMPTY(timeoutq))
LL_PUSH(timeoutq, x); //x=timeoutq=head of list
//insert it correct place and update timout
else
LL_EACH(timeoutq,tempptr,struct event)
{
if(x->timeout <= tempptr->timeout)
{
tempptr->timeout -= x->timeout;
LL_L_INSERT(tempptr,x);
break;
}
else
{
if(LL_NEXT(timeoutq,tempptr) == NULL)
{
x->timeout -= tempptr->timeout;
LL_R_INSERT(tempptr,x);
break;
}
else
{
x->timeout -= tempptr->timeout;
continue; //go to the next node
}
}
}
//update then_usec
then_usec = now_usec() - then_usec;
}
//
// bring the time current
// check the list to see if anything expired
// if so, do it - and either return it to the freelist
// or put it back into the timeoutq
//
// return whether or not you handled anything
//
int
handle_timeoutq_event( )
{
struct event *ep;
//struct event *head_timeoutq;
ep = (struct event *)LL_HEAD(timeoutq); //ep now points to the head of TimeoutQ
//if diff < 1 us then execute the function
if(ep->timeout - then_usec < 1 )
{
//execute function
pfv_t tmp = ep->go;
(* tmp)(ep->data);
//remove from the timeoutq and reinsert back to freelist
LL_DETACH(timeoutq, ep);
if(ep->repeat_interval != 0)
{
create_timeoutq_event( ep->repeat_interval, ep->repeat_interval, ep->go, ep->data);
//update then_usec
then_usec -= now_usec();
}
else
{
//push to freelist
LL_PUSH(freelist,ep);
}
return 1;
}
else
return 0;
}