]> err.no Git - linux-2.6/blob - arch/um/os-Linux/time.c
uml: fix timer switching
[linux-2.6] / arch / um / os-Linux / time.c
1 /*
2  * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com)
3  * Licensed under the GPL
4  */
5
6 #include <stddef.h>
7 #include <errno.h>
8 #include <signal.h>
9 #include <time.h>
10 #include <sys/time.h>
11 #include "kern_constants.h"
12 #include "os.h"
13 #include "user.h"
14
15 static int is_real_timer = 0;
16
17 int set_interval(int is_virtual)
18 {
19         int usec = 1000000/UM_HZ;
20         int timer_type = is_virtual ? ITIMER_VIRTUAL : ITIMER_REAL;
21         struct itimerval interval = ((struct itimerval) { { 0, usec },
22                                                           { 0, usec } });
23
24         if (setitimer(timer_type, &interval, NULL) == -1)
25                 return -errno;
26
27         return 0;
28 }
29
30 void disable_timer(void)
31 {
32         struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
33
34         if ((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) ||
35             (setitimer(ITIMER_REAL, &disable, NULL) < 0))
36                 printk(UM_KERN_ERR "disable_timer - setitimer failed, "
37                        "errno = %d\n", errno);
38
39         /* If there are signals already queued, after unblocking ignore them */
40         signal(SIGALRM, SIG_IGN);
41         signal(SIGVTALRM, SIG_IGN);
42 }
43
44 int switch_timers(int to_real)
45 {
46         struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
47         struct itimerval enable;
48         int old, new, old_type = is_real_timer;
49
50         if(to_real == old_type)
51                 return to_real;
52
53         if (to_real) {
54                 old = ITIMER_VIRTUAL;
55                 new = ITIMER_REAL;
56         }
57         else {
58                 old = ITIMER_REAL;
59                 new = ITIMER_VIRTUAL;
60         }
61
62         if (setitimer(old, &disable, &enable) < 0)
63                 printk(UM_KERN_ERR "switch_timers - setitimer disable failed, "
64                        "errno = %d\n", errno);
65
66         if((enable.it_value.tv_sec == 0) && (enable.it_value.tv_usec == 0))
67                 enable.it_value = enable.it_interval;
68
69         if (setitimer(new, &enable, NULL))
70                 printk(UM_KERN_ERR "switch_timers - setitimer enable failed, "
71                        "errno = %d\n", errno);
72
73         is_real_timer = to_real;
74         return old_type;
75 }
76
77 unsigned long long os_nsecs(void)
78 {
79         struct timeval tv;
80
81         gettimeofday(&tv, NULL);
82         return (unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000;
83 }
84
85 void idle_sleep(int secs)
86 {
87         struct timespec ts;
88
89         ts.tv_sec = secs;
90         ts.tv_nsec = 0;
91         nanosleep(&ts, NULL);
92 }