source: trunk/packages/xen-3.1/xen-3.1/tools/vnet/vnetd/timer.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 4.1 KB
Line 
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>
23
24#include "allocate.h"
25#include "timer.h"
26
27#define MODULE_NAME "TIMER"
28#undef DEBUG
29#define DEBUG 1
30#include "debug.h"
31
32static Timer *timers = NULL;
33
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 */
39double 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}
44
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 */
52static int itimer_set(double expiry){
53    struct itimerval val = {};
54    struct itimerval old = {};
55    double now, delay;
56    int err = 0;
57
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}
71
72void Timer_free(Timer *z){
73#ifndef USE_GC
74    if(!z) return;
75    deallocate(z);
76#endif
77}
78
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 */
90int 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->data);
97    }
98    timers = curr;
99    itimer_set((curr ? curr->expiry : 0));
100    return 0;
101}
102
103void Timer_add(Timer *timer){
104    // Insert timer in list ordered by (increasing) expiry time.
105    Timer *prev, *curr, *next;
106    prev = NULL;
107    for(curr = timers; curr; prev = curr, curr = next){
108        next = curr->next;
109        if(timer->expiry < curr->expiry) break;
110    }
111    if(prev){
112        prev->next = timer;
113    } else {
114        timers = timer;
115    }
116    timer->next = curr;
117
118    // Set interval timer to go off for earliest expiry time.
119    itimer_set(timer->expiry);
120}
121
122Timer * Timer_set(double delay, TimerFn *fn, unsigned long data){
123    // Get 'now'.
124    double now = time_now();
125    Timer *timer = NULL;
126    timer = ALLOCATE(Timer);
127    if(!timer) goto exit;
128    // Add delay to now to get expiry time.
129    timer->expiry = now + delay;
130    timer->fn = fn;
131    timer->data = data;
132
133    Timer_add(timer);
134  exit:
135    return timer;
136}
137
138int Timer_cancel(Timer *timer){
139    // Remove timer from list.
140    int err = -ENOENT;
141    Timer *prev, *curr, *next;
142    for(prev = NULL, curr = timers; curr; prev = curr, curr = next){
143        next = curr->next;
144        if(curr == timer){
145            err = 0;
146            if(prev){
147                prev->next = curr->next;
148            } else {
149                timers = curr->next;
150            }
151            curr->next = NULL;
152            break;
153        }
154    }
155    return err;
156}
157
Note: See TracBrowser for help on using the repository browser.