a5abc85425990c839d1e62fad179fe78febcf2fb
[dragonfly.git] / lib / libatm / timer.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
8  * This Host ATM Research Platform ("HARP") file (the "Software") is
9  * made available by Network Computing Services, Inc. ("NetworkCS")
10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
11  * support of any kind.
12  *
13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17  * In no event shall NetworkCS be responsible for any damages, including
18  * but not limited to consequential damages, arising from or relating to
19  * any use of the Software or related support.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/lib/libatm/timer.c,v 1.3.2.1 2001/09/28 16:52:10 dillon Exp $
27  *      @(#) $DragonFly: src/lib/libatm/timer.c,v 1.4 2008/11/10 15:58:20 swildner Exp $
28  *
29  */
30
31 #include <sys/cdefs.h>
32
33 /*
34  * User Space Library Functions
35  * ----------------------------
36  *
37  * Timer functions
38  *
39  */
40
41 #include <sys/types.h>
42 #include <sys/param.h>
43 #include <sys/socket.h>
44 #include <net/if.h>
45 #include <netinet/in.h>
46 #include <netatm/port.h>
47 #include <netatm/queue.h>
48 #include <netatm/atm.h>
49 #include <netatm/atm_if.h>
50 #include <netatm/atm_sap.h>
51 #include <netatm/atm_sys.h>
52 #include <netatm/atm_ioctl.h>
53
54 #include <errno.h>
55 #include <signal.h>
56
57 #include "libatm.h"
58
59 Harp_timer      *harp_timer_head;
60 int             harp_timer_exec;
61
62
63 /*
64  * Process a HARP timer tick
65  *
66  * This function is called via the SIGALRM signal.  It increments
67  * harp_timer_exec.  The user should check this flag frequently and
68  * call timer_proc when it is set.
69  *
70  * Arguments:
71  *      None
72  *
73  * Returns:
74  *      None
75  *
76  */
77 static void
78 timer_tick(int signo __unused)
79 {
80         /*
81          * Bump the timer flag
82          */
83         harp_timer_exec++;
84 }
85
86
87 /*
88  * Process HARP timers
89  *
90  * This function is called after a SIGALRM signal is posted.  It runs
91  * down the list of timer entries, calling the specified functions
92  * for any timers that have expired.
93  *
94  * Arguments:
95  *      None
96  *
97  * Returns:
98  *      None
99  *
100  */
101 void
102 timer_proc(void)
103 {
104         Harp_timer      *htp;
105         void            (*f)();
106
107         /*
108          * Reset marks in all timers on the queue
109          */
110         for (htp = harp_timer_head; htp; htp = htp->ht_next) {
111                 htp->ht_mark = -1;
112         }
113
114         /*
115          * Run through timer chain decrementing each timer.
116          * If an expired timer is found, take the timer block
117          * off the chain and call the specified function.  A
118          * timer's action can result in other timers being
119          * cancelled (taken off the queue), so every time we
120          * call a user function, we start over from the top of
121          * the list.
122          */
123 timer_cont:
124         for (htp = harp_timer_head; htp; htp = htp->ht_next) {
125                 /*
126                  * Make sure we only process each entry once and
127                  * don't process entries that are put on the queue
128                  * by user functions we call for this tick
129                  */
130                 if (htp->ht_mark == -1) {
131                         /*
132                          * Decrement the timer and mark that we've
133                          * processed the entry
134                          */
135                         htp->ht_ticks -= harp_timer_exec;
136                         htp->ht_mark = 1;
137
138                         /*
139                          * Check whether the timer is expired
140                          */
141                         if (htp->ht_ticks <= 0) {
142                                 /*
143                                  * Unlink the timer block and call
144                                  * the user function
145                                  */
146                                 f = htp->ht_func;
147                                 UNLINK(htp, Harp_timer, harp_timer_head,
148                                                 ht_next);
149                                 f(htp);
150
151                                 /*
152                                  * Start over
153                                  */
154                                 goto timer_cont;
155                         }
156                 }
157         }
158
159         /*
160          * Reset the timer exec flag
161          */
162         harp_timer_exec = 0;
163 }
164
165
166 /*
167  * Start the timer
168  *
169  * Set up the SIGALRM signal handler and set up the real-time
170  * timer to tick once per second.
171  *
172  * Arguments:
173  *      None
174  *
175  * Returns:
176  *      0       success
177  *      errno   reason for failure
178  *
179  */
180 int
181 init_timer(void)
182 {
183         int                     rc = 0;
184         struct itimerval        timeval;
185
186         /*
187          * Clear the timer flag
188          */
189         harp_timer_exec = 0;
190
191         /*
192          * Set up signal handler
193          */
194         if (signal(SIGALRM, timer_tick) == SIG_ERR) {
195                 return(errno);
196         }
197
198         /*
199          * Start timer
200          */
201         timeval.it_value.tv_sec = 1;
202         timeval.it_value.tv_usec = 0;
203         timeval.it_interval.tv_sec = 1;
204         timeval.it_interval.tv_usec = 0;
205
206         if (setitimer(ITIMER_REAL, &timeval,
207                         NULL) == -1) {
208                 rc = errno;
209                 (void)signal(SIGALRM, SIG_DFL);
210         }
211
212         return(rc);
213 }
214
215
216 /*
217  * Block timers from firing
218  *
219  * Block the SIGALRM signal.
220  *
221  * Arguments:
222  *      None
223  *
224  * Returns:
225  *      mask    the previous blocked signal mask
226  *
227  */
228 int
229 block_timer(void)
230 {
231         /*
232          * Block the SIGALRM signal
233          */
234         return(sigblock(sigmask(SIGALRM)));
235 }
236
237
238 /*
239  * Re-enable timers
240  *
241  * Restore the signal mask (presumably one that was returned by
242  * block_timer).
243  *
244  * Arguments:
245  *      mask    the signal mask to be restored
246  *
247  * Returns:
248  *      mask    the previous blocked signal mask
249  *
250  */
251 void
252 enable_timer(int mask)
253 {
254         /*
255          * Set the signal mask
256          */
257         sigsetmask(mask);
258
259         return;
260 }