ia64/xen-unstable

view tools/vnet/vnetd/timer.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
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 }