ia64/xen-unstable

view tools/vnet/vnetd/timer.c @ 8740:3d7ea7972b39

Update patches for linux 2.6.15.

Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Thu Feb 02 17:16:00 2006 +0000 (2006-02-02)
parents 0a4b76b6b5a0
children 71b0f00f6344
line source
1 /*
2 * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
3 *
4 * This library is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; either version 2.1 of the License, or
7 * (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <errno.h>
21 #include <sys/time.h>
22 #include <time.h>
24 #include "allocate.h"
25 #include "timer.h"
27 #define MODULE_NAME "TIMER"
28 #undef DEBUG
29 #define DEBUG 1
30 #include "debug.h"
32 static Timer *timers = NULL;
34 /** Get the time now as a double (in seconds).
35 * Returns zero if could not get the time.
36 *
37 * @return time now
38 */
39 double time_now(void){
40 struct timeval time;
41 if(gettimeofday(&time, NULL)) return 0.0;
42 return (double)time.tv_sec + (1.0e-6 * (double)time.tv_usec);
43 }
45 /** Set the process real-time timer to go off at a given expiry time.
46 * The timer will not be set to go off in less than 10 ms
47 * (even if the expiry time is sooner, or in the past).
48 *
49 * @param expiry time (in seconds)
50 * @return 0 on success, error code otherwise
51 */
52 static int timer_set(double expiry){
53 struct itimerval val = {};
54 struct itimerval old = {};
55 double now, delay;
56 int err = 0;
58 if(expiry == 0.0){
59 val.it_value.tv_sec = 0;
60 val.it_value.tv_usec = 0;
61 } else {
62 now = time_now();
63 delay = expiry - now;
64 if(delay < 0.01) delay = 0.01;
65 val.it_value.tv_sec = (long)delay;
66 val.it_value.tv_usec = (long)((delay - (double)(long)delay) * 1.0e6);
67 }
68 err = setitimer(ITIMER_REAL, &val, &old);
69 return err;
70 }
72 static void Timer_free(Timer *z){
73 #ifndef USE_GC
74 if(!z) return;
75 deallocate(z);
76 #endif
77 }
79 /** Process any expired timers.
80 * Calls the functions of expired timers and removes them
81 * from the timer list.
82 * Reschedules the interval timer for the earliest expiring timer
83 * (if any).
84 *
85 * Should not be called from within the SIGALRM handler - set
86 * a flag there and call it later.
87 *
88 * @return 0 on success, error code otherwise.
89 */
90 int process_timers(void){
91 double now = time_now();
92 Timer *curr, *next;
93 for(curr = timers; curr; curr = next){
94 next = curr->next;
95 if(curr->expiry > now) break;
96 if(curr->fn) curr->fn(curr);
97 Timer_free(curr);
98 }
99 timers = curr;
100 timer_set((curr ? curr->expiry : 0));
101 return 0;
102 }
104 Timer * Timer_set(double delay, TimerFn *fn, void *data){
105 // Get 'now'.
106 double now = time_now();
107 Timer *timer = NULL, *prev, *curr, *next;
108 timer = ALLOCATE(Timer);
109 if(!timer) goto exit;
110 // Add delay to now to get expiry time.
111 timer->expiry = now + delay;
112 timer->fn = fn;
113 timer->data = data;
115 // Insert timer in list ordered by (increasing) expiry time.
116 prev = NULL;
117 for(curr = timers; curr; prev = curr, curr = next){
118 next = curr->next;
119 if(timer->expiry < curr->expiry) break;
120 }
121 if(prev){
122 prev->next = timer;
123 } else {
124 timers = timer;
125 }
126 timer->next = curr;
128 // Set interval timer to go off for earliest expiry time.
129 timer_set(timer->expiry);
130 exit:
131 return timer;
132 }
134 int Timer_cancel(Timer *timer){
135 // Remove timer from list.
136 int err = -ENOENT;
137 Timer *prev, *curr, *next;
138 for(prev = NULL, curr = timers; curr; prev = curr, curr = next){
139 next = curr->next;
140 if(curr == timer){
141 err = 0;
142 if(prev){
143 prev->next = curr->next;
144 } else {
145 timers = curr->next;
146 }
147 curr->next = NULL;
148 Timer_free(curr);
149 break;
150 }
151 }
152 return err;
153 }