Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2eb5f31b authored by Anton Ivanov's avatar Anton Ivanov Committed by Richard Weinberger
Browse files

um: Switch clocksource to hrtimers



UML is using an obsolete itimer call for
all timers and "polls" for kernel space timer firing
in its userspace portion resulting in a long list
of bugs and incorrect behaviour(s). It also uses
ITIMER_VIRTUAL for its timer which results in the
timer being dependent on it running and the cpu
load.

This patch fixes this by moving to posix high resolution
timers firing off CLOCK_MONOTONIC and relaying the timer
correctly to the UML userspace.

Fixes:
 - crashes when hosts suspends/resumes
 - broken userspace timers - effecive ~40Hz instead
   of what they should be. Note - this modifies skas behavior
   by no longer setting an itimer per clone(). Timer events
   are relayed instead.
 - kernel network packet scheduling disciplines
 - tcp behaviour especially under load
 - various timer related corner cases

Finally, overall responsiveness of userspace is better.

Signed-off-by: default avatarThomas Meyer <thomas@m3y3r.de>
Signed-off-by: default avatarAnton Ivanov <aivanov@brocade.com>
[rw: massaged commit message]
Signed-off-by: default avatarRichard Weinberger <richard@nod.at>
parent e17c6d77
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -131,7 +131,7 @@ export LDS_ELF_FORMAT := $(ELF_FORMAT)
# The wrappers will select whether using "malloc" or the kernel allocator.
LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc

LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt))
LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt)) -lrt

# Used by link-vmlinux.sh which has special support for um link
export CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE)
+13 −5
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk})
 * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
 * Licensed under the GPL
 */
@@ -183,6 +185,7 @@ extern int create_mem_file(unsigned long long len);
/* process.c */
extern unsigned long os_process_pc(int pid);
extern int os_process_parent(int pid);
extern void os_alarm_process(int pid);
extern void os_stop_process(int pid);
extern void os_kill_process(int pid, int reap_child);
extern void os_kill_ptraced_process(int pid, int reap_child);
@@ -217,7 +220,7 @@ extern int set_umid(char *name);
extern char *get_umid(void);

/* signal.c */
extern void timer_init(void);
extern void timer_set_signal_handler(void);
extern void set_sigstack(void *sig_stack, int size);
extern void remove_sigstack(void);
extern void set_handler(int sig);
@@ -227,6 +230,7 @@ extern void unblock_signals(void);
extern int get_signals(void);
extern int set_signals(int enable);
extern int os_is_signal_stack(void);
extern void deliver_alarm(void);

/* util.c */
extern void stack_protections(unsigned long address);
@@ -238,12 +242,16 @@ extern void um_early_printk(const char *s, unsigned int n);
extern void os_fix_helper_signals(void);

/* time.c */
extern void idle_sleep(unsigned long long nsecs);
extern int set_interval(void);
extern int timer_one_shot(int ticks);
extern long long disable_timer(void);
extern void os_idle_sleep(unsigned long long nsecs);
extern int os_timer_create(void* timer);
extern int os_timer_set_interval(void* timer, void* its);
extern int os_timer_one_shot(int ticks);
extern long long os_timer_disable(void);
extern long os_timer_remain(void* timer);
extern void uml_idle_timer(void);
extern long long os_persistent_clock_emulation(void);
extern long long os_nsecs(void);
extern long long os_vnsecs(void);

/* skas/mem.c */
extern long run_syscall_stub(struct mm_id * mm_idp,
+4 −3
Original line number Diff line number Diff line
/*

 * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
 * Copyright (C) 2005 Jeff Dike (jdike@karaya.com)
 * Licensed under the GPL
 */
@@ -6,12 +8,11 @@
#ifndef __STUB_DATA_H
#define __STUB_DATA_H

#include <sys/time.h>
#include <time.h>

struct stub_data {
	long offset;
	unsigned long offset;
	int fd;
	struct itimerval timer;
	long err;
};

+13 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 - 2014 Cisco Systems
 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
 * Licensed under the GPL
 */

#ifndef __TIMER_INTERNAL_H__
#define __TIMER_INTERNAL_H__

#define TIMER_MULTIPLIER 256
#define TIMER_MIN_DELTA  500

#endif
+4 −4
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk})
 * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
 * Copyright 2003 PathScale, Inc.
 * Licensed under the GPL
@@ -27,6 +29,7 @@
#include <kern_util.h>
#include <os.h>
#include <skas.h>
#include <timer-internal.h>

/*
 * This is a per-cpu array.  A processor only modifies its entry and it only
@@ -203,11 +206,8 @@ void initial_thread_cb(void (*proc)(void *), void *arg)

void arch_cpu_idle(void)
{
	unsigned long long nsecs;

	cpu_tasks[current_thread_info()->cpu].pid = os_getpid();
	nsecs = disable_timer();
	idle_sleep(nsecs);
	os_idle_sleep(UM_NSEC_PER_SEC);
	local_irq_enable();
}

Loading