Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] uml: move libc-dependent time code

The serial UML OS-abstraction layer patch (um/kernel dir).

This moves all systemcalls from time.c file under os-Linux dir and joins
time.c and tine_kernel.c files

Signed-off-by: Gennady Sharapov <Gennady.V.Sharapov@intel.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Gennady Sharapov and committed by
Linus Torvalds
cff65c4f 4fef0c10

+213 -96
+11 -1
arch/um/include/os.h
··· 190 190 int r, int w, int x); 191 191 extern int os_unmap_memory(void *addr, int len); 192 192 extern void os_flush_stdout(void); 193 - extern unsigned long long os_usecs(void); 194 193 195 194 /* tt.c 196 195 * for tt mode only (will be deleted in future...) ··· 243 244 extern void setup_machinename(char *machine_out); 244 245 extern void setup_hostinfo(void); 245 246 extern int setjmp_wrapper(void (*proc)(void *, void *), ...); 247 + 248 + /* time.c */ 249 + #define BILLION (1000 * 1000 * 1000) 250 + 251 + extern void switch_timers(int to_real); 252 + extern void idle_sleep(int secs); 253 + extern void enable_timer(void); 254 + extern void disable_timer(void); 255 + extern void user_time_init(void); 256 + extern void uml_idle_timer(void); 257 + extern unsigned long long os_nsecs(void); 246 258 247 259 #endif
-19
arch/um/include/time_user.h
··· 1 - /* 2 - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 3 - * Licensed under the GPL 4 - */ 5 - 6 - #ifndef __TIME_USER_H__ 7 - #define __TIME_USER_H__ 8 - 9 - extern void timer(void); 10 - extern void switch_timers(int to_real); 11 - extern void idle_sleep(int secs); 12 - extern void enable_timer(void); 13 - extern void prepare_timer(void * ptr); 14 - extern void disable_timer(void); 15 - extern unsigned long time_lock(void); 16 - extern void time_unlock(unsigned long); 17 - extern void user_time_init(void); 18 - 19 - #endif
+2 -2
arch/um/kernel/Makefile
··· 9 9 obj-y = config.o exec_kern.o exitcode.o \ 10 10 init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ 11 11 process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ 12 - signal_kern.o smp.o syscall_kern.o sysrq.o time.o \ 12 + signal_kern.o smp.o syscall_kern.o sysrq.o \ 13 13 time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o 14 14 15 15 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o ··· 23 23 24 24 user-objs-$(CONFIG_TTY_LOG) += tty_log.o 25 25 26 - USER_OBJS := $(user-objs-y) config.o time.o tty_log.o 26 + USER_OBJS := $(user-objs-y) config.o tty_log.o 27 27 28 28 include arch/um/scripts/Makefile.rules 29 29
-1
arch/um/kernel/exec_kern.c
··· 17 17 #include "irq_user.h" 18 18 #include "tlb.h" 19 19 #include "os.h" 20 - #include "time_user.h" 21 20 #include "choose-mode.h" 22 21 #include "mode_kern.h" 23 22
-1
arch/um/kernel/process_kern.c
··· 39 39 #include "init.h" 40 40 #include "irq_user.h" 41 41 #include "mem_user.h" 42 - #include "time_user.h" 43 42 #include "tlb.h" 44 43 #include "frame_kern.h" 45 44 #include "sigcontext.h"
-1
arch/um/kernel/skas/process.c
··· 18 18 #include <asm/types.h> 19 19 #include "user.h" 20 20 #include "ptrace_user.h" 21 - #include "time_user.h" 22 21 #include "sysdep/ptrace.h" 23 22 #include "user_util.h" 24 23 #include "kern_util.h"
-1
arch/um/kernel/skas/process_kern.c
··· 13 13 #include "asm/uaccess.h" 14 14 #include "asm/atomic.h" 15 15 #include "kern_util.h" 16 - #include "time_user.h" 17 16 #include "skas.h" 18 17 #include "os.h" 19 18 #include "user_util.h"
+2 -2
arch/um/kernel/syscall.c
··· 25 25 syscall_record[index].syscall = syscall; 26 26 syscall_record[index].pid = current_pid(); 27 27 syscall_record[index].result = 0xdeadbeef; 28 - syscall_record[index].start = os_usecs(); 28 + syscall_record[index].start = os_nsecs(); 29 29 return(index); 30 30 } 31 31 32 32 void record_syscall_end(int index, long result) 33 33 { 34 34 syscall_record[index].result = result; 35 - syscall_record[index].end = os_usecs(); 35 + syscall_record[index].end = os_nsecs(); 36 36 }
+76 -48
arch/um/kernel/time_kern.c
··· 1 - /* 1 + /* 2 2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) 3 3 * Licensed under the GPL 4 4 */ ··· 13 13 #include "linux/interrupt.h" 14 14 #include "linux/init.h" 15 15 #include "linux/delay.h" 16 + #include "linux/hrtimer.h" 16 17 #include "asm/irq.h" 17 18 #include "asm/param.h" 18 19 #include "asm/current.h" 19 20 #include "kern_util.h" 20 21 #include "user_util.h" 21 - #include "time_user.h" 22 22 #include "mode.h" 23 23 #include "os.h" 24 24 ··· 39 39 int timer_irq_inited = 0; 40 40 41 41 static int first_tick; 42 - static unsigned long long prev_usecs; 42 + static unsigned long long prev_nsecs; 43 43 #ifdef CONFIG_UML_REAL_TIME_CLOCK 44 44 static long long delta; /* Deviation per interval */ 45 45 #endif ··· 58 58 if(first_tick){ 59 59 #ifdef CONFIG_UML_REAL_TIME_CLOCK 60 60 /* We've had 1 tick */ 61 - unsigned long long usecs = os_usecs(); 61 + unsigned long long nsecs = os_nsecs(); 62 62 63 - delta += usecs - prev_usecs; 64 - prev_usecs = usecs; 63 + delta += nsecs - prev_nsecs; 64 + prev_nsecs = nsecs; 65 65 66 66 /* Protect against the host clock being set backwards */ 67 67 if(delta < 0) 68 68 delta = 0; 69 69 70 - ticks += (delta * HZ) / MILLION; 71 - delta -= (ticks * MILLION) / HZ; 70 + ticks += (delta * HZ) / BILLION; 71 + delta -= (ticks * BILLION) / HZ; 72 72 #else 73 73 ticks = 1; 74 74 #endif 75 75 } 76 76 else { 77 - prev_usecs = os_usecs(); 77 + prev_nsecs = os_nsecs(); 78 78 first_tick = 1; 79 79 } 80 80 ··· 88 88 { 89 89 struct pt_regs regs; 90 90 91 - CHOOSE_MODE((void) 91 + CHOOSE_MODE((void) 92 92 (UPT_SC(&regs.regs) = (struct sigcontext *) (&sig + 1)), 93 93 (void) (regs.regs.skas.is_user = 0)); 94 94 do_timer(&regs); 95 95 } 96 96 97 + static DEFINE_SPINLOCK(timer_spinlock); 98 + 99 + static unsigned long long local_offset = 0; 100 + 101 + static inline unsigned long long get_time(void) 102 + { 103 + unsigned long long nsecs; 104 + unsigned long flags; 105 + 106 + spin_lock_irqsave(&timer_spinlock, flags); 107 + nsecs = os_nsecs(); 108 + nsecs += local_offset; 109 + spin_unlock_irqrestore(&timer_spinlock, flags); 110 + 111 + return nsecs; 112 + } 113 + 97 114 irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) 98 115 { 116 + unsigned long long nsecs; 99 117 unsigned long flags; 100 118 101 119 do_timer(regs); 120 + 102 121 write_seqlock_irqsave(&xtime_lock, flags); 103 - timer(); 122 + nsecs = get_time() + local_offset; 123 + xtime.tv_sec = nsecs / NSEC_PER_SEC; 124 + xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; 104 125 write_sequnlock_irqrestore(&xtime_lock, flags); 126 + 105 127 return(IRQ_HANDLED); 106 128 } 107 129 108 130 long um_time(int __user *tloc) 109 131 { 110 - struct timeval now; 132 + long ret = get_time() / NSEC_PER_SEC; 111 133 112 - do_gettimeofday(&now); 113 - if (tloc) { 114 - if (put_user(now.tv_sec, tloc)) 115 - now.tv_sec = -EFAULT; 116 - } 117 - return now.tv_sec; 134 + if((tloc != NULL) && put_user(ret, tloc)) 135 + return -EFAULT; 136 + 137 + return ret; 138 + } 139 + 140 + void do_gettimeofday(struct timeval *tv) 141 + { 142 + unsigned long long nsecs = get_time(); 143 + 144 + tv->tv_sec = nsecs / NSEC_PER_SEC; 145 + /* Careful about calculations here - this was originally done as 146 + * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC 147 + * which gave bogus (> 1000000) values. Dunno why, suspect gcc 148 + * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion 149 + * problem that I missed. 150 + */ 151 + nsecs -= tv->tv_sec * NSEC_PER_SEC; 152 + tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC; 153 + } 154 + 155 + static inline void set_time(unsigned long long nsecs) 156 + { 157 + unsigned long long now; 158 + unsigned long flags; 159 + 160 + spin_lock_irqsave(&timer_spinlock, flags); 161 + now = os_nsecs(); 162 + local_offset = nsecs - now; 163 + spin_unlock_irqrestore(&timer_spinlock, flags); 164 + 165 + clock_was_set(); 118 166 } 119 167 120 168 long um_stime(int __user *tptr) 121 169 { 122 170 int value; 123 - struct timespec new; 124 171 125 172 if (get_user(value, tptr)) 126 173 return -EFAULT; 127 - new.tv_sec = value; 128 - new.tv_nsec = 0; 129 - do_settimeofday(&new); 174 + 175 + set_time((unsigned long long) value * NSEC_PER_SEC); 176 + 177 + return 0; 178 + } 179 + 180 + int do_settimeofday(struct timespec *tv) 181 + { 182 + set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec); 183 + 130 184 return 0; 131 185 } 132 186 ··· 194 140 local_irq_enable(); 195 141 if(current_thread->cpu == 0) 196 142 timer_irq(regs); 197 - } 198 - 199 - static DEFINE_SPINLOCK(timer_spinlock); 200 - 201 - unsigned long time_lock(void) 202 - { 203 - unsigned long flags; 204 - 205 - spin_lock_irqsave(&timer_spinlock, flags); 206 - return(flags); 207 - } 208 - 209 - void time_unlock(unsigned long flags) 210 - { 211 - spin_unlock_irqrestore(&timer_spinlock, flags); 212 143 } 213 144 214 145 int __init timer_init(void) ··· 210 171 } 211 172 212 173 __initcall(timer_init); 213 - 214 - /* 215 - * Overrides for Emacs so that we follow Linus's tabbing style. 216 - * Emacs will notice this stuff at the end of the file and automatically 217 - * adjust the settings for this buffer only. This must remain at the end 218 - * of the file. 219 - * --------------------------------------------------------------------------- 220 - * Local variables: 221 - * c-file-style: "linux" 222 - * End: 223 - */
-1
arch/um/kernel/tt/exec_kern.c
··· 13 13 #include "user_util.h" 14 14 #include "kern_util.h" 15 15 #include "irq_user.h" 16 - #include "time_user.h" 17 16 #include "mem_user.h" 18 17 #include "os.h" 19 18 #include "tlb.h"
-1
arch/um/kernel/tt/process_kern.c
··· 18 18 #include "os.h" 19 19 #include "kern.h" 20 20 #include "sigcontext.h" 21 - #include "time_user.h" 22 21 #include "mem_user.h" 23 22 #include "tlb.h" 24 23 #include "mode.h"
-1
arch/um/os-Linux/main.c
··· 16 16 #include "user_util.h" 17 17 #include "kern_util.h" 18 18 #include "mem_user.h" 19 - #include "time_user.h" 20 19 #include "irq_user.h" 21 20 #include "user.h" 22 21 #include "init.h"
+1 -1
arch/um/os-Linux/signal.c
··· 18 18 #include "sysdep/sigcontext.h" 19 19 #include "sysdep/signal.h" 20 20 #include "sigcontext.h" 21 - #include "time_user.h" 22 21 #include "mode.h" 22 + #include "os.h" 23 23 24 24 void sig_handler(ARCH_SIGHDLR_PARAM) 25 25 {
-1
arch/um/os-Linux/start_up.c
··· 29 29 #include "irq_user.h" 30 30 #include "ptrace_user.h" 31 31 #include "mem_user.h" 32 - #include "time_user.h" 33 32 #include "init.h" 34 33 #include "os.h" 35 34 #include "uml-config.h"
+121 -14
arch/um/os-Linux/time.c
··· 1 - #include <stdlib.h> 2 - #include <sys/time.h> 1 + /* 2 + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 3 + * Licensed under the GPL 4 + */ 3 5 4 - unsigned long long os_usecs(void) 6 + #include <stdio.h> 7 + #include <stdlib.h> 8 + #include <unistd.h> 9 + #include <time.h> 10 + #include <sys/time.h> 11 + #include <signal.h> 12 + #include <errno.h> 13 + #include "user_util.h" 14 + #include "kern_util.h" 15 + #include "user.h" 16 + #include "process.h" 17 + #include "kern_constants.h" 18 + #include "os.h" 19 + 20 + /* XXX This really needs to be declared and initialized in a kernel file since 21 + * it's in <linux/time.h> 22 + */ 23 + extern struct timespec wall_to_monotonic; 24 + 25 + static void set_interval(int timer_type) 26 + { 27 + int usec = 1000000/hz(); 28 + struct itimerval interval = ((struct itimerval) { { 0, usec }, 29 + { 0, usec } }); 30 + 31 + if(setitimer(timer_type, &interval, NULL) == -1) 32 + panic("setitimer failed - errno = %d\n", errno); 33 + } 34 + 35 + void enable_timer(void) 36 + { 37 + set_interval(ITIMER_VIRTUAL); 38 + } 39 + 40 + void disable_timer(void) 41 + { 42 + struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); 43 + if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) || 44 + (setitimer(ITIMER_REAL, &disable, NULL) < 0)) 45 + printk("disnable_timer - setitimer failed, errno = %d\n", 46 + errno); 47 + /* If there are signals already queued, after unblocking ignore them */ 48 + set_handler(SIGALRM, SIG_IGN, 0, -1); 49 + set_handler(SIGVTALRM, SIG_IGN, 0, -1); 50 + } 51 + 52 + void switch_timers(int to_real) 53 + { 54 + struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); 55 + struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() }, 56 + { 0, 1000000/hz() }}); 57 + int old, new; 58 + 59 + if(to_real){ 60 + old = ITIMER_VIRTUAL; 61 + new = ITIMER_REAL; 62 + } 63 + else { 64 + old = ITIMER_REAL; 65 + new = ITIMER_VIRTUAL; 66 + } 67 + 68 + if((setitimer(old, &disable, NULL) < 0) || 69 + (setitimer(new, &enable, NULL))) 70 + printk("switch_timers - setitimer failed, errno = %d\n", 71 + errno); 72 + } 73 + 74 + void uml_idle_timer(void) 75 + { 76 + if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) 77 + panic("Couldn't unset SIGVTALRM handler"); 78 + 79 + set_handler(SIGALRM, (__sighandler_t) alarm_handler, 80 + SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); 81 + set_interval(ITIMER_REAL); 82 + } 83 + 84 + extern void ktime_get_ts(struct timespec *ts); 85 + #define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts) 86 + 87 + void time_init(void) 88 + { 89 + struct timespec now; 90 + 91 + if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR) 92 + panic("Couldn't set SIGVTALRM handler"); 93 + set_interval(ITIMER_VIRTUAL); 94 + 95 + do_posix_clock_monotonic_gettime(&now); 96 + wall_to_monotonic.tv_sec = -now.tv_sec; 97 + wall_to_monotonic.tv_nsec = -now.tv_nsec; 98 + } 99 + 100 + unsigned long long os_nsecs(void) 5 101 { 6 102 struct timeval tv; 7 103 8 104 gettimeofday(&tv, NULL); 9 - return((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec); 105 + return((unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000); 10 106 } 11 107 12 - /* 13 - * Overrides for Emacs so that we follow Linus's tabbing style. 14 - * Emacs will notice this stuff at the end of the file and automatically 15 - * adjust the settings for this buffer only. This must remain at the end 16 - * of the file. 17 - * --------------------------------------------------------------------------- 18 - * Local variables: 19 - * c-file-style: "linux" 20 - * End: 21 - */ 108 + void idle_sleep(int secs) 109 + { 110 + struct timespec ts; 111 + 112 + ts.tv_sec = secs; 113 + ts.tv_nsec = 0; 114 + nanosleep(&ts, NULL); 115 + } 116 + 117 + /* XXX This partly duplicates init_irq_signals */ 118 + 119 + void user_time_init(void) 120 + { 121 + set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, 122 + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, 123 + SIGALRM, SIGUSR2, -1); 124 + set_handler(SIGALRM, (__sighandler_t) alarm_handler, 125 + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, 126 + SIGVTALRM, SIGUSR2, -1); 127 + set_interval(ITIMER_VIRTUAL); 128 + }
-1
arch/um/os-Linux/tt.c
··· 27 27 #include "sysdep/sigcontext.h" 28 28 #include "irq_user.h" 29 29 #include "ptrace_user.h" 30 - #include "time_user.h" 31 30 #include "init.h" 32 31 #include "os.h" 33 32 #include "uml-config.h"