#include #include #include #include #include "dat.h" #include "fns.h" #include "linux.h" struct linux_timezone { int tz_minuteswest; int tz_dsttime; }; static struct linux_timezone systz; void inittime(void) { Tm *t; boottime = nsec(); systz.tz_minuteswest = 0; systz.tz_dsttime = 0; if(t = localtime(time(nil))) systz.tz_minuteswest = t->tzoff / 60; } int sys_time(long *p) { return time(p); } int sys_clock_gettime(int clock, void *t) { struct linux_timespec *ts = t; vlong x; trace("sys_clock_gettime(%d, %p)", clock, t); x = nsec(); ts->tv_sec = (long)(x/1000000000LL); ts->tv_nsec = (long)(x%1000000000LL); return 0; } int sys_gettimeofday(void *tvp, void *tzp) { struct linux_timeval *tv = tvp; struct linux_timezone *tz = tzp; vlong t; trace("sys_gettimeofday(%p, %p)", tvp, tzp); t = nsec(); tv->tv_sec = (long)(t/1000000000LL); tv->tv_usec = (long)((t%1000000000LL)/1000); if(tz) *tz = systz; return 0; } int sys_nanosleep(void *rqp, void *rmp) { struct linux_timespec *req = rqp; struct linux_timespec *rem = rmp; vlong t, now; int err; trace("sys_nanosleep(%p, %p)", rqp, rmp); if(req == nil) return -EFAULT; if(req->tv_sec < 0 || req->tv_nsec < 0 || req->tv_nsec >= 1000000000LL) return -EINVAL; now = nsec(); if(current->restart->syscall){ t = current->restart->nanosleep.timeout; } else { t = now + req->tv_sec*1000000000LL + req->tv_nsec; } if(now < t){ if(notifyme(1)) err = -1; else { err = sleep((t - now) / 1000000LL); notifyme(0); } if(err < 0){ now = nsec(); if(now < t){ current->restart->nanosleep.timeout = t; if(rem != nil){ t -= now; rem->tv_sec = (long)(t/1000000000LL); rem->tv_nsec = (long)(t%1000000000LL); } return -ERESTART; } } } return 0; } int proctimes(Uproc *p, ulong *t) { char buf[1024], *f[12]; int fd, n; t[0] = t[1] = t[2] = t[3] = 0; snprint(buf, sizeof(buf), "/proc/%d/status", p->kpid); if((fd = open(buf, OREAD)) < 0) return mkerror(); if((n = read(fd, buf, sizeof(buf)-1)) <= 0){ close(fd); return mkerror(); } close(fd); buf[n] = 0; if(getfields(buf, f, 12, 1, "\t ") != 12) return -EIO; t[0] = atoi(f[2])*HZ / 1000; t[1] = atoi(f[3])*HZ / 1000; t[2] = atoi(f[4])*HZ / 1000; t[3] = atoi(f[5])*HZ / 1000; return 0; } struct linux_tms { long tms_utime; long tms_stime; long tms_cutime; long tms_cstime; }; int sys_times(void *m) { struct linux_tms *x = m; ulong t[4]; int err; trace("sys_times(%p)", m); if(x != nil){ if((err = proctimes(current, t)) < 0) return err; x->tms_utime = t[0]; x->tms_stime = t[1]; x->tms_cutime = t[2]; x->tms_cstime = t[3]; } return (HZ*(nsec() - boottime)) / 1000000000LL; }