summaryrefslogtreecommitdiff
path: root/arch/um/os-Linux
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r--arch/um/os-Linux/skas/process.c27
-rw-r--r--arch/um/os-Linux/time.c17
2 files changed, 39 insertions, 5 deletions
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 0036164bb0fb..3e64814e888e 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -287,10 +287,18 @@ int start_userspace(unsigned long stub_stack)
void userspace(struct uml_pt_regs *regs)
{
+ struct itimerval timer;
+ unsigned long long nsecs, now;
int err, status, op, pid = userspace_pid[0];
/* To prevent races if using_sysemu changes under us.*/
int local_using_sysemu;
+ if (getitimer(ITIMER_VIRTUAL, &timer))
+ printk("Failed to get itimer, errno = %d\n", errno);
+ nsecs = timer.it_value.tv_sec * BILLION +
+ timer.it_value.tv_usec * 1000;
+ nsecs += os_nsecs();
+
while (1) {
restore_registers(pid, regs);
@@ -333,8 +341,18 @@ void userspace(struct uml_pt_regs *regs)
case SIGTRAP:
relay_signal(SIGTRAP, regs);
break;
- case SIGIO:
case SIGVTALRM:
+ now = os_nsecs();
+ if(now < nsecs)
+ break;
+ block_signals();
+ (*sig_info[sig])(sig, regs);
+ unblock_signals();
+ nsecs = timer.it_value.tv_sec * BILLION +
+ timer.it_value.tv_usec * 1000;
+ nsecs += os_nsecs();
+ break;
+ case SIGIO:
case SIGILL:
case SIGBUS:
case SIGFPE:
@@ -378,6 +396,7 @@ __initcall(init_thread_regs);
int copy_context_skas0(unsigned long new_stack, int pid)
{
+ struct timeval tv = { .tv_sec = 0, .tv_usec = 1000000 / UM_HZ };
int err;
unsigned long current_stack = current_stub_stack();
struct stub_data *data = (struct stub_data *) current_stack;
@@ -392,9 +411,9 @@ int copy_context_skas0(unsigned long new_stack, int pid)
*data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset),
.fd = new_fd,
.timer = ((struct itimerval)
- { { 0, 1000000 / UM_HZ },
- { 0, 1000000 / UM_HZ }})
- });
+ { .it_value = tv,
+ .it_interval = tv }) });
+
err = ptrace_setregs(pid, thread_regs);
if (err < 0)
panic("copy_context_skas0 : PTRACE_SETREGS failed, "
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index 6ff3d98281ba..9ffc61ac8ed6 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -26,6 +26,21 @@ int set_interval(void)
return 0;
}
+int timer_one_shot(int ticks)
+{
+ unsigned long usec = ticks * 1000000 / UM_HZ;
+ unsigned long sec = usec / 1000000;
+ struct itimerval interval;
+
+ usec %= 1000000;
+ interval = ((struct itimerval) { { 0, 0 }, { sec, usec } });
+
+ if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1)
+ return -errno;
+
+ return 0;
+}
+
void disable_timer(void)
{
struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
@@ -74,7 +89,7 @@ unsigned long long os_nsecs(void)
struct timeval tv;
gettimeofday(&tv, NULL);
- return (unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000;
+ return timeval_to_ns(&tv);
}
void idle_sleep(int secs)