add linux_emul base, reorganize docs
[openbsd_emul.git] / linux_emul_base / time.c
1 #include <u.h>
2 #include <libc.h>
3 #include <ureg.h>
4 #include <tos.h>
5 #include "dat.h"
6 #include "fns.h"
7 #include "linux.h"
8
9 struct linux_timezone
10 {
11 int tz_minuteswest;
12 int tz_dsttime;
13 };
14
15 static struct linux_timezone systz;
16
17 void
18 inittime(void)
19 {
20 Tm *t;
21
22 boottime = nsec();
23
24 systz.tz_minuteswest = 0;
25 systz.tz_dsttime = 0;
26
27 if(t = localtime(time(nil)))
28 systz.tz_minuteswest = t->tzoff / 60;
29 }
30
31 int sys_time(long *p)
32 {
33 return time(p);
34 }
35
36 int sys_clock_gettime(int clock, void *t)
37 {
38 struct linux_timespec *ts = t;
39 vlong x;
40
41 trace("sys_clock_gettime(%d, %p)", clock, t);
42 x = nsec();
43 ts->tv_sec = (long)(x/1000000000LL);
44 ts->tv_nsec = (long)(x%1000000000LL);
45 return 0;
46 }
47
48 int sys_gettimeofday(void *tvp, void *tzp)
49 {
50 struct linux_timeval *tv = tvp;
51 struct linux_timezone *tz = tzp;
52 vlong t;
53
54 trace("sys_gettimeofday(%p, %p)", tvp, tzp);
55
56 t = nsec();
57 tv->tv_sec = (long)(t/1000000000LL);
58 tv->tv_usec = (long)((t%1000000000LL)/1000);
59
60 if(tz)
61 *tz = systz;
62
63 return 0;
64 }
65
66 int sys_nanosleep(void *rqp, void *rmp)
67 {
68 struct linux_timespec *req = rqp;
69 struct linux_timespec *rem = rmp;
70 vlong t, now;
71 int err;
72
73 trace("sys_nanosleep(%p, %p)", rqp, rmp);
74
75 if(req == nil)
76 return -EFAULT;
77 if(req->tv_sec < 0 || req->tv_nsec < 0 || req->tv_nsec >= 1000000000LL)
78 return -EINVAL;
79
80 now = nsec();
81 if(current->restart->syscall){
82 t = current->restart->nanosleep.timeout;
83 } else {
84 t = now + req->tv_sec*1000000000LL + req->tv_nsec;
85 }
86
87 if(now < t){
88 if(notifyme(1))
89 err = -1;
90 else {
91 err = sleep((t - now) / 1000000LL);
92 notifyme(0);
93 }
94 if(err < 0){
95 now = nsec();
96 if(now < t){
97 current->restart->nanosleep.timeout = t;
98 if(rem != nil){
99 t -= now;
100 rem->tv_sec = (long)(t/1000000000LL);
101 rem->tv_nsec = (long)(t%1000000000LL);
102 }
103 return -ERESTART;
104 }
105 }
106 }
107
108 return 0;
109 }
110
111 int proctimes(Uproc *p, ulong *t)
112 {
113 char buf[1024], *f[12];
114 int fd, n;
115
116 t[0] = t[1] = t[2] = t[3] = 0;
117 snprint(buf, sizeof(buf), "/proc/%d/status", p->kpid);
118 if((fd = open(buf, OREAD)) < 0)
119 return mkerror();
120 if((n = read(fd, buf, sizeof(buf)-1)) <= 0){
121 close(fd);
122 return mkerror();
123 }
124 close(fd);
125 buf[n] = 0;
126 if(getfields(buf, f, 12, 1, "\t ") != 12)
127 return -EIO;
128 t[0] = atoi(f[2])*HZ / 1000;
129 t[1] = atoi(f[3])*HZ / 1000;
130 t[2] = atoi(f[4])*HZ / 1000;
131 t[3] = atoi(f[5])*HZ / 1000;
132 return 0;
133 }
134
135 struct linux_tms
136 {
137 long tms_utime;
138 long tms_stime;
139 long tms_cutime;
140 long tms_cstime;
141 };
142
143 int sys_times(void *m)
144 {
145 struct linux_tms *x = m;
146 ulong t[4];
147 int err;
148
149 trace("sys_times(%p)", m);
150
151 if(x != nil){
152 if((err = proctimes(current, t)) < 0)
153 return err;
154 x->tms_utime = t[0];
155 x->tms_stime = t[1];
156 x->tms_cutime = t[2];
157 x->tms_cstime = t[3];
158 }
159 return (HZ*(nsec() - boottime)) / 1000000000LL;
160 }