Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 74371
b: refs/heads/master
c: 364e3a3
h: refs/heads/master
i:
  74369: 7dbdb82
  74367: d85c5fd
v: v3
  • Loading branch information
Jeff Dike authored and Linus Torvalds committed Nov 29, 2007
1 parent 3d124bb commit 6fcd82a
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9fc89c2dea7ca7915e6606e49167cdca2f3c4e30
refs/heads/master: 364e3a3d8a26aae058cf1c257457ad1f6b1cfe4c
54 changes: 51 additions & 3 deletions trunk/arch/um/os-Linux/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ long long disable_timer(void)
{
struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } });

if(setitimer(ITIMER_VIRTUAL, &time, &time) < 0)
if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0)
printk(UM_KERN_ERR "disable_timer - setitimer failed, "
"errno = %d\n", errno);

Expand All @@ -74,13 +74,61 @@ long long os_nsecs(void)
return timeval_to_ns(&tv);
}

#ifdef UML_CONFIG_NO_HZ
static int after_sleep_interval(struct timespec *ts)
{
}
#else
static inline long long timespec_to_us(const struct timespec *ts)
{
return ((long long) ts->tv_sec * UM_USEC_PER_SEC) +
ts->tv_nsec / UM_NSEC_PER_USEC;
}

static int after_sleep_interval(struct timespec *ts)
{
int usec = UM_USEC_PER_SEC / UM_HZ;
long long start_usecs = timespec_to_us(ts);
struct timeval tv;
struct itimerval interval;

/*
* It seems that rounding can increase the value returned from
* setitimer to larger than the one passed in. Over time,
* this will cause the remaining time to be greater than the
* tick interval. If this happens, then just reduce the first
* tick to the interval value.
*/
if (start_usecs > usec)
start_usecs = usec;
tv = ((struct timeval) { .tv_sec = start_usecs / UM_USEC_PER_SEC,
.tv_usec = start_usecs % UM_USEC_PER_SEC });
interval = ((struct itimerval) { { 0, usec }, tv });

if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1)
return -errno;

return 0;
}
#endif

extern void alarm_handler(int sig, struct sigcontext *sc);

void idle_sleep(unsigned long long nsecs)
{
struct timespec ts = { .tv_sec = nsecs / UM_NSEC_PER_SEC,
.tv_nsec = nsecs % UM_NSEC_PER_SEC };
struct timespec ts;

/*
* nsecs can come in as zero, in which case, this starts a
* busy loop. To prevent this, reset nsecs to the tick
* interval if it is zero.
*/
if (nsecs == 0)
nsecs = UM_NSEC_PER_SEC / UM_HZ;
ts = ((struct timespec) { .tv_sec = nsecs / UM_NSEC_PER_SEC,
.tv_nsec = nsecs % UM_NSEC_PER_SEC });

if (nanosleep(&ts, &ts) == 0)
alarm_handler(SIGVTALRM, NULL);
after_sleep_interval(&ts);
}

0 comments on commit 6fcd82a

Please sign in to comment.