lkml.org 
[lkml]   [2000]   [Jan]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
From
Date
Subject[patch] High-resolution process timers
This patch enables very low-overhead access to high-resolution process virtual
time and, optionally, high-resolution virtualized user and system time.

If enabled, a page of memory containing timing values is allocated with each
task_struct, and an extra per-pid proc entry (/proc/PID/hrtime) is created
which, when mmapped, maps the timing page into the user's address space. All
process timing queries can be then be performed at memory reference speeds,
without the overhead of a system call. Timers work at the resolution of the
hardware timestamp counters. For convenience, a library is provided which can
be used to perform the mapping and timer querying.

In the current implementation, permissions on /proc/PID/hrtime are set to 400.

The library and the latest version of the patch against various 2.2 and 2.3
kernels is available at http://www.cs.wisc.edu/paradyn/libhrtime/. The
following patch is against 2.3.39

These timers were developed as part of the Paradyn Parallel Performance Tools
project at the University of Wisconsin.

-nick

diff -rc5N linux-2.3.39/Documentation/Configure.help linux-2.3.39-hrtime/Documentation/Configure.help
*** linux-2.3.39/Documentation/Configure.help Mon Jan 10 20:25:32 2000
--- linux-2.3.39-hrtime/Documentation/Configure.help Tue Jan 11 13:47:39 2000
***************
*** 116,125 ****
--- 116,142 ----
Documentation/smp.txt, and Documentation/IO-APIC.txt. Also see the
SMP-FAQ on the WWW at http://www.irisa.fr/prive/mentre/smp-faq/ .

If you don't know what to do here, say N.

+ High-resolution process virtual time
+ CONFIG_HRTIME
+ This enables cycle-counter precision for process virtual time.
+ A timing page per task is allocated where the values are kept.
+ /proc/PID/hrtime can then be mmapped to access these values from
+ user space without having to do a syscall.
+
+ If you don't know what to do here, say N.
+
+ High-resolution process user and system time
+ CONFIG_HRUSTIME
+ This enables cycle-counter precision for virtualized user and system
+ time. Warning: Turning this option on will add code to the system
+ call path.
+
+ If you don't know what to do here, say N.
+
Kernel math emulation
CONFIG_MATH_EMULATION
Linux can emulate a math coprocessor (used for floating point
operations) if you don't have one. 486DX and Pentium processors have
a math coprocessor built in, 486SX and 386 do not, unless you added
diff -rc5N linux-2.3.39/arch/i386/config.in linux-2.3.39-hrtime/arch/i386/config.in
*** linux-2.3.39/arch/i386/config.in Thu Jan 6 17:01:56 2000
--- linux-2.3.39-hrtime/arch/i386/config.in Tue Jan 11 13:47:39 2000
***************
*** 28,45 ****
define_bool CONFIG_X86_WP_WORKS_OK y
define_bool CONFIG_X86_INVLPG y
define_bool CONFIG_X86_BSWAP y
define_bool CONFIG_X86_POPAD_OK y
fi
! if [ "$CONFIG_M686" = "y" -o "$CONFIG_M586TSC" = "y" ]; then
define_bool CONFIG_X86_TSC y
fi
if [ "$CONFIG_M686" = "y" ]; then
define_bool CONFIG_X86_GOOD_APIC y
fi
if [ "$CONFIG_MK7" = "y" ]; then
- define_bool CONFIG_X86_TSC y
define_bool CONFIG_X86_GOOD_APIC y
define_bool CONFIG_X86_USE_3DNOW y
fi

choice 'High Memory Support' \
--- 28,48 ----
define_bool CONFIG_X86_WP_WORKS_OK y
define_bool CONFIG_X86_INVLPG y
define_bool CONFIG_X86_BSWAP y
define_bool CONFIG_X86_POPAD_OK y
fi
!
! if [ "$CONFIG_M686" = "y" -o "$CONFIG_M586TSC" = "y" -o "$CONFIG_MK7" = "y" ]; then
define_bool CONFIG_X86_TSC y
+ else
+ define_bool CONFIG_X86_TSC n
fi
+
if [ "$CONFIG_M686" = "y" ]; then
define_bool CONFIG_X86_GOOD_APIC y
fi
if [ "$CONFIG_MK7" = "y" ]; then
define_bool CONFIG_X86_GOOD_APIC y
define_bool CONFIG_X86_USE_3DNOW y
fi

choice 'High Memory Support' \
***************
*** 55,64 ****
--- 58,75 ----
fi

bool 'Math emulation' CONFIG_MATH_EMULATION
bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR
bool 'Symmetric multi-processing support' CONFIG_SMP
+
+ if [ "$CONFIG_X86_TSC" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool 'High-resolution process virtual time support' CONFIG_HRTIME
+ if [ "$CONFIG_HRTIME" = "y" ]; then
+ bool 'High-resolution process utime/stime support' CONFIG_HRUSTIME
+ fi
+ fi
+
endmenu

mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
diff -rc5N linux-2.3.39/arch/i386/defconfig linux-2.3.39-hrtime/arch/i386/defconfig
*** linux-2.3.39/arch/i386/defconfig Sat Jan 8 15:16:30 2000
--- linux-2.3.39-hrtime/arch/i386/defconfig Tue Jan 11 13:47:39 2000
***************
*** 28,37 ****
--- 28,39 ----
# CONFIG_HIGHMEM4G is not set
# CONFIG_HIGHMEM64G is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_MTRR is not set
CONFIG_SMP=y
+ # CONFIG_HRTIME is not set
+ # CONFIG_HRUSTIME is not set

#
# Loadable module support
#
CONFIG_MODULES=y
diff -rc5N linux-2.3.39/arch/i386/kernel/entry.S linux-2.3.39-hrtime/arch/i386/kernel/entry.S
*** linux-2.3.39/arch/i386/kernel/entry.S Mon Jan 10 20:15:58 2000
--- linux-2.3.39-hrtime/arch/i386/kernel/entry.S Tue Jan 11 13:47:39 2000
***************
*** 41,50 ****
--- 41,51 ----
*/

#include <linux/sys.h>
#include <linux/linkage.h>
#include <asm/segment.h>
+ #include <linux/config.h>
#define ASSEMBLY
#include <asm/smp.h>

EBX = 0x00
ECX = 0x04
***************
*** 74,83 ****
--- 75,96 ----
flags = 4
sigpending = 8
addr_limit = 12
exec_domain = 16
need_resched = 20
+ #ifdef CONFIG_HRUSTIME
+ hrtime = 24
+
+ /* The following are offsets into the hrtime_struct, not the task_struct */
+ last_us_dispatch_low = 0
+ last_us_dispatch_high = 4
+ utime_low = 8
+ utime_high = 12
+ stime_low = 16
+ stime_high = 20
+ in_system = 24
+ #endif

ENOSYS = 38


#define SAVE_ALL \
***************
*** 195,206 ****
--- 208,245 ----
GET_CURRENT(%ebx)
cmpl $(NR_syscalls),%eax
jae badsys
testb $0x20,flags(%ebx) # PF_TRACESYS
jne tracesys
+ #ifdef CONFIG_HRUSTIME
+ pushl %eax
+ rdtsc # edx:eax has current timespamp value
+ movl hrtime(%ebx), %ebx # ebx now points to the htrime_struct
+ subl last_us_dispatch_low(%ebx), %eax
+ sbbl last_us_dispatch_high(%ebx), %edx # edx:eax has number of tics since last dispatch
+ addl %eax, utime_low(%ebx)
+ adcl %edx, utime_high(%ebx)
+ addl %eax, last_us_dispatch_low(%ebx)
+ adcl %edx, last_us_dispatch_high(%ebx)
+ addl $1, in_system(%ebx)
+ GET_CURRENT(%ebx)
+ popl %eax # reload the system call number XXX - fixme
+ #endif
call *SYMBOL_NAME(sys_call_table)(,%eax,4)
movl %eax,EAX(%esp) # save the return value
+ #ifdef CONFIG_HRUSTIME
+ rdtsc # edx:eax has current timespamp value
+ movl hrtime(%ebx), %ebx # ebx now points to the htrime_struct
+ subl last_us_dispatch_low(%ebx), %eax
+ sbbl last_us_dispatch_high(%ebx), %edx # edx:eax has number of tics since last dispatch
+ addl %eax, stime_low(%ebx)
+ adcl %edx, stime_high(%ebx)
+ addl %eax, last_us_dispatch_low(%ebx)
+ adcl %edx, last_us_dispatch_high(%ebx)
+ subl $1, in_system(%ebx)
+ GET_CURRENT(%ebx)
+ #endif
ALIGN
.globl ret_from_sys_call
.globl ret_from_intr
ret_from_sys_call:
movl SYMBOL_NAME(bh_mask),%eax
diff -rc5N linux-2.3.39/arch/i386/kernel/init_task.c linux-2.3.39-hrtime/arch/i386/kernel/init_task.c
*** linux-2.3.39/arch/i386/kernel/init_task.c Tue Aug 3 12:32:57 1999
--- linux-2.3.39-hrtime/arch/i386/kernel/init_task.c Tue Jan 11 13:47:39 2000
***************
*** 1,18 ****
--- 1,25 ----
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
+ #include <linux/config.h>
+ #ifdef CONFIG_HRTIME
+ #include <linux/hrtime.h>
+ #endif

#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/desc.h>

static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM(init_mm);
+ #ifdef CONFIG_HRTIME
+ static struct hrtime_struct init_hrtime = INIT_HRTIME;
+ #endif

/*
* Initial task structure.
*
* We need to make sure that this is 8192-byte aligned due to the
diff -rc5N linux-2.3.39/fs/proc/Makefile linux-2.3.39-hrtime/fs/proc/Makefile
*** linux-2.3.39/fs/proc/Makefile Tue Dec 21 00:05:10 1999
--- linux-2.3.39-hrtime/fs/proc/Makefile Tue Jan 11 13:47:39 2000
***************
*** 11,20 ****
--- 11,23 ----
O_OBJS := inode.o root.o base.o generic.o array.o \
kmsg.o proc_tty.o proc_misc.o kcore.o
ifdef CONFIG_OMIRR
O_OBJS := $(O_OBJS) omirr.o
endif
+ ifdef CONFIG_HRTIME
+ O_OBJS := $(O_OBJS) hrtime.o
+ endif
OX_OBJS := procfs_syms.o
M_OBJS :=

ifeq ($(CONFIG_PROC_DEVICETREE),y)
O_OBJS += proc_devtree.o
diff -rc5N linux-2.3.39/fs/proc/base.c linux-2.3.39-hrtime/fs/proc/base.c
*** linux-2.3.39/fs/proc/base.c Fri Jan 7 14:59:42 2000
--- linux-2.3.39-hrtime/fs/proc/base.c Tue Jan 11 13:47:39 2000
***************
*** 496,505 ****
--- 496,508 ----
PROC_PID_ENVIRON,
PROC_PID_CMDLINE,
PROC_PID_STAT,
PROC_PID_STATM,
PROC_PID_MAPS,
+ #if CONFIG_HRTIME
+ PROC_PID_HRTIME,
+ #endif
#if CONFIG_AP1000
PROC_PID_RINGBUF,
#endif
PROC_PID_CPU,
PROC_PID_FD_DIR = 0x8000, /* 0x8000-0xffff */
***************
*** 514,523 ****
--- 517,529 ----
E(PROC_PID_STAT, "stat", S_IFREG|S_IRUGO),
E(PROC_PID_STATM, "statm", S_IFREG|S_IRUGO),
#ifdef __SMP__
E(PROC_PID_CPU, "cpu", S_IFREG|S_IRUGO),
#endif
+ #ifdef CONFIG_HRTIME
+ E(PROC_PID_HRTIME, "hrtime", S_IFREG|S_IRUSR),
+ #endif
#if CONFIG_AP1000
E(PROC_PID_RINGBUF, "ringbuf", S_IFREG|S_IRUGO|S_IWUSR),
#endif
E(PROC_PID_MAPS, "maps", S_IFREG|S_IRUGO),
E(PROC_PID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
***************
*** 867,876 ****
--- 873,887 ----
break;
#ifdef __SMP__
case PROC_PID_CPU:
inode->i_op = &proc_info_inode_operations;
inode->u.proc_i.op.proc_read = proc_pid_cpu;
+ break;
+ #endif
+ #ifdef CONFIG_HRTIME
+ case PROC_PID_HRTIME:
+ inode->i_op = &proc_hrtime_inode_operations;
break;
#endif
#if CONFIG_AP1000
case PROC_PID_RINGBUF:
inode->i_op = &proc_ringbuf_inode_operations;
diff -rc5N linux-2.3.39/fs/proc/hrtime.c linux-2.3.39-hrtime/fs/proc/hrtime.c
*** linux-2.3.39/fs/proc/hrtime.c Wed Dec 31 19:00:00 1969
--- linux-2.3.39-hrtime/fs/proc/hrtime.c Tue Jan 11 13:47:39 2000
***************
*** 0 ****
--- 1,252 ----
+ /*
+ * linux/fs/proc/hrtime.c
+ *
+ * Copyright (C) 1999, Nick Rasmussen <nick@jive.org>
+ */
+
+ #include <linux/types.h>
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+ #include <linux/proc_fs.h>
+ #include <linux/hrtime.h>
+ #include <linux/config.h>
+
+ #include <asm/page.h>
+ #include <asm/mman.h>
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+ #include <asm/pgtable.h>
+
+ #define PROC_BLOCK_SIZE (3*1024)
+
+ static void hrtime_vm_close(struct vm_area_struct *area)
+ {
+ unref_hrtime_struct((struct hrtime_struct *) area->vm_file->private_data);
+ }
+
+ static struct vm_operations_struct hrtime_vm_ops = {
+ NULL, /* open */
+ hrtime_vm_close, /* close */
+ NULL, /* unmap */
+ NULL, /* protect */
+ NULL, /* sync */
+ NULL, /* advise */
+ NULL, /* nopage */
+ NULL, /* wppage */
+ NULL /* swapout */
+ };
+
+ #define HRTIME_ENABLE_READ 0
+
+ #if HRTIME_ENABLE_READ
+ static int print_hrtime(struct hrtime_struct *h, char * buffer)
+ {
+ int len = 0;
+
+ /* XXX - this assumes little endian - FIXME */
+ len += sprintf(buffer + len,
+ "hrtime: start_time 0x%08x%08x",
+ ((unsigned int *) &h->start_time)[1],
+ ((unsigned int *) &h->start_time)[0]);
+
+ len += sprintf(buffer + len,
+ " vtime 0x%08x%08x",
+ ((unsigned int *) &h->vtime)[1],
+ ((unsigned int *) &h->vtime)[0]);
+
+ #ifdef CONFIG_HRUSTIME
+ len += sprintf(buffer + len,
+ " utime 0x%08x%08x",
+ ((unsigned int *) &h->utime)[1],
+ ((unsigned int *) &h->utime)[0]);
+
+ len += sprintf(buffer + len,
+ " stime 0x%08x%08x",
+ ((unsigned int *) &h->stime)[1],
+ ((unsigned int *) &h->stime)[0]);
+
+ len += sprintf(buffer + len,
+ " in_system %ld",
+ h->in_system);
+ #endif
+
+ len += sprintf(buffer + len,
+ " ref %ld\n",
+ h->refcount);
+
+ return len;
+ }
+
+
+ static ssize_t hrtime_read(struct file * file, char * buf,
+ size_t count, loff_t *ppos)
+ {
+ unsigned long page;
+ ssize_t length;
+ ssize_t end;
+
+ if (count > PROC_BLOCK_SIZE)
+ count = PROC_BLOCK_SIZE;
+ if (!(page = __get_free_page(GFP_KERNEL)))
+ return -ENOMEM;
+
+ length = print_hrtime((struct hrtime_struct *) file->private_data,
+ (char *) page);
+
+ if (length < 0) {
+ free_page(page);
+ return length;
+ }
+
+ if (*ppos >= length) {
+ free_page(page);
+ return 0;
+ }
+
+ if (count + *ppos > length)
+ count = length - *ppos;
+
+ end = count + *ppos;
+ copy_to_user(buf, (char *) page + *ppos, count);
+ *ppos = end;
+ free_page(page);
+ return count;
+ }
+
+ #endif /* HRTIME_ENABLE_READ */
+
+ /*
+ * hrtime_mmap will map another (or your own) process' hrtime_struct
+ * into your address space.
+ */
+ int hrtime_mmap(struct file *file, struct vm_area_struct * vma)
+ {
+ int error = 0;
+
+ vma->vm_ops = &hrtime_vm_ops;
+
+ read_lock(&tasklist_lock);
+
+ /* The timing page can only be mapped readonly */
+ if ((pgprot_val(vma->vm_page_prot) & PROT_WRITE) != 0) {
+ error = -EPERM;
+ goto exit_with_unlock;
+ }
+
+ /* We only allow mapping exactly one page -- the hrtime page */
+ if (vma->vm_end - vma->vm_start != PAGE_SIZE) {
+ error = -EINVAL;
+ goto exit_with_unlock;
+ }
+
+ error = remap_page_range(vma->vm_start,
+ virt_to_phys(file->private_data),
+ PAGE_SIZE, vma->vm_page_prot);
+
+ if (error == 0)
+ ref_hrtime_struct((struct hrtime_struct *) file->private_data);
+
+ exit_with_unlock:
+
+ read_unlock(&tasklist_lock);
+
+ return error;
+ }
+
+ static int hrtime_open(struct inode *inode, struct file *file)
+ {
+ unsigned int pid;
+ int error = 0;
+ struct task_struct * tsk;
+
+ pid = inode->i_ino >> 16;
+
+ if (!pid) {
+ return -EBADF;
+ }
+
+ file->private_data = 0;
+
+ read_lock(&tasklist_lock);
+
+ tsk = current;
+
+ if (pid != tsk->pid)
+ tsk = find_task_by_pid(pid);
+
+ if (tsk == NULL)
+ {
+ error = -ESRCH;
+ goto exit_with_unlock;
+ }
+
+ file->private_data = tsk->hrtime;
+
+ ref_hrtime_struct(file->private_data);
+
+ exit_with_unlock:
+
+ read_unlock(&tasklist_lock);
+ return error;
+ }
+
+ /*
+ * When closing /proc/PID/hrtime, unref the respective processes hrtime field
+ */
+ static int hrtime_release(struct inode *inode, struct file *file)
+ {
+ /* Do I really need to grab the tasklist lock here? I am changing
+ * fields inside a potential task.
+ */
+ read_lock(&tasklist_lock);
+
+ if (file->private_data != 0) {
+ unref_hrtime_struct(file->private_data);
+ }
+
+ read_unlock(&tasklist_lock);
+
+ return 0;
+ }
+
+ static struct file_operations proc_hrtime_operations = {
+ NULL, /* no lseek */
+ #if HRTIME_ENABLE_READ
+ hrtime_read, /* read */
+ #else
+ NULL, /* no read */
+ #endif
+ NULL, /* no write */
+ NULL, /* no readdir */
+ NULL, /* no poll */
+ NULL, /* no ioctl */
+ hrtime_mmap, /* mmap */
+ hrtime_open, /* open */
+ NULL, /* flush */
+ hrtime_release, /* release */
+ NULL /* can't fsync */
+ };
+
+ struct inode_operations proc_hrtime_inode_operations = {
+ &proc_hrtime_operations, /* file-ops */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* get_block */
+ NULL, /* readpage */
+ NULL, /* writepage */
+ NULL, /* truncate */
+ NULL, /* permission */
+ NULL /* revalidate */
+ };
+
diff -rc5N linux-2.3.39/include/asm-i386/hrtime.h linux-2.3.39-hrtime/include/asm-i386/hrtime.h
*** linux-2.3.39/include/asm-i386/hrtime.h Wed Dec 31 19:00:00 1969
--- linux-2.3.39-hrtime/include/asm-i386/hrtime.h Tue Jan 11 13:47:39 2000
***************
*** 0 ****
--- 1,23 ----
+ #ifndef _ASM_HRTIME_H
+ #define _ASM_HRTIME_H
+ /*
+ * linux/include/asm-i386/hrtime.h
+ *
+ * Copyright (C) 1999, Nick Rasmussen <nick@jive.org>
+ */
+
+ #include <linux/config.h>
+
+ #include <asm/msr.h>
+
+ typedef unsigned long long hrtime_t;
+
+ static inline void get_current_hrtime(volatile hrtime_t *t)
+ {
+ volatile unsigned long *parts = (volatile unsigned long *) t;
+
+ rdtsc(parts[0], parts[1]);
+ return;
+ }
+
+ #endif
diff -rc5N linux-2.3.39/include/linux/hrtime.h linux-2.3.39-hrtime/include/linux/hrtime.h
*** linux-2.3.39/include/linux/hrtime.h Wed Dec 31 19:00:00 1969
--- linux-2.3.39-hrtime/include/linux/hrtime.h Tue Jan 11 13:47:39 2000
***************
*** 0 ****
--- 1,68 ----
+ #ifndef _LINUX_HRTIME_H
+ #define _LINUX_HRTIME_H
+ /*
+ * include/linux/hrtime.h
+ *
+ * High-resolution process timing
+ *
+ * Copyright (C) 1999, Nick Rasmussen <nick@jive.org>
+ */
+
+ #include <linux/config.h>
+ #include <linux/spinlock.h>
+
+ #include <asm/hrtime.h>
+
+ /* Will be 1 once the cpu-cpu offset code for smp boxes is written */
+ #define HRTIME_HAS_OFFSETS 0
+
+ /*
+ * Careful if you add fields to this struct - the offsets to utime and
+ * stime are hard-coded in arch/i386/kernel/entry.S
+ */
+ struct hrtime_struct
+ {
+ /* These fields are only used if CONFIG_USTIME is enabled */
+ /* dispatch times are non-zero only when the process is executing */
+ volatile hrtime_t last_us_dispatch;
+ volatile hrtime_t utime;
+ volatile hrtime_t stime;
+ volatile long in_system;
+
+ /* A flag as to wether CONFIG_USTIME is enabled. This is so that
+ * the hrtime interface can be binary compatible between kernels
+ * compiled with and without CONFIG_USTIME
+ */
+ long has_ustime;
+
+ /* start_time's value is with reference to cpu0 */
+ hrtime_t start_time;
+
+ /* dispatch times are non-zero only when the process is executing */
+ volatile hrtime_t last_dispatch;
+ volatile hrtime_t vtime;
+
+ volatile long offset_to_cpu0;
+
+ long refcount;
+ spinlock_t reflock;
+ };
+
+ #ifdef __KERNEL__
+
+ #ifdef CONFIG_HRUSTIME
+ #define INIT_HRTIME { 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, SPIN_LOCK_UNLOCKED }
+ #else
+ #define INIT_HRTIME { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, SPIN_LOCK_UNLOCKED }
+ #endif
+
+ extern struct hrtime_struct init_hrtime;
+
+ extern struct hrtime_struct *alloc_hrtime_struct(void);
+ extern void init_hrtime_struct(struct hrtime_struct *s);
+ extern void ref_hrtime_struct(struct hrtime_struct *s);
+ extern void unref_hrtime_struct(struct hrtime_struct *s);
+
+ #endif /* __KERNEL__ */
+
+ #endif
diff -rc5N linux-2.3.39/include/linux/proc_fs.h linux-2.3.39-hrtime/include/linux/proc_fs.h
*** linux-2.3.39/include/linux/proc_fs.h Mon Jan 10 20:30:03 2000
--- linux-2.3.39-hrtime/include/linux/proc_fs.h Tue Jan 11 13:47:39 2000
***************
*** 113,122 ****
--- 113,125 ----
extern struct dentry *proc_lookup(struct inode *, struct dentry *);

extern struct inode_operations proc_sys_inode_operations;
extern struct inode_operations proc_kcore_inode_operations;
extern struct inode_operations proc_kmsg_inode_operations;
+ #if CONFIG_HRTIME
+ extern struct inode_operations proc_hrtime_inode_operations;
+ #endif
#if CONFIG_AP1000
extern struct inode_operations proc_ringbuf_inode_operations;
#endif
extern struct inode_operations proc_omirr_inode_operations;
extern struct inode_operations proc_ppc_htab_inode_operations;
diff -rc5N linux-2.3.39/include/linux/sched.h linux-2.3.39-hrtime/include/linux/sched.h
*** linux-2.3.39/include/linux/sched.h Mon Jan 10 20:29:22 2000
--- linux-2.3.39-hrtime/include/linux/sched.h Tue Jan 11 13:51:43 2000
***************
*** 22,31 ****
--- 22,35 ----
#include <linux/tty.h>
#include <linux/sem.h>
#include <linux/signal.h>
#include <linux/securebits.h>

+ #ifdef CONFIG_HRTIME
+ #include <linux/hrtime.h>
+ #endif
+
/*
* cloning flags:
*/
#define CSIGNAL 0x000000ff /* signal mask to be sent at exit */
#define CLONE_VM 0x00000100 /* set if VM shared between processes */
***************
*** 272,281 ****
--- 276,289 ----
0-0xFFFFFFFF for kernel-thread
*/
struct exec_domain *exec_domain;
volatile long need_resched;

+ #ifdef CONFIG_HRTIME
+ struct hrtime_struct *hrtime;
+ #endif
+
cycles_t avg_slice;
int lock_depth; /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */
/* begin intel cache line */
long counter;
long priority;
***************
*** 392,401 ****
--- 400,450 ----

/*
* INIT_TASK is used to set up the first task table, touch at
* your own risk!. Base=0, limit=0x1fffff (=2MB)
*/
+ #ifdef CONFIG_HRTIME
+ #define INIT_TASK(name) \
+ /* state etc */ { 0,0,0,KERNEL_DS,&default_exec_domain,0, \
+ /* hrtime */ &init_hrtime, \
+ /* avg_slice */ 0, -1, \
+ /* counter */ DEF_PRIORITY,DEF_PRIORITY,SCHED_OTHER, \
+ /* mm */ NULL, &init_mm, \
+ /* has_cpu */ 0,0, \
+ /* run_list */ LIST_HEAD_INIT(init_task.run_list), \
+ /* next_task */ &init_task,&init_task, \
+ /* last_proc */ 0, \
+ /* binfmt */ NULL, \
+ /* ec,brk... */ 0,0,0,0,0,0, \
+ /* pid etc.. */ 0,0,0,0,0, \
+ /* proc links*/ &init_task,&init_task,NULL,NULL,NULL, \
+ /* pidhash */ NULL, NULL, \
+ /* chld wait */ __WAIT_QUEUE_HEAD_INITIALIZER(name.wait_chldexit), NULL, \
+ /* timeout */ 0,0,0,0,0,0,0, \
+ /* timer */ { NULL, NULL, 0, 0, it_real_fn }, \
+ /* utime */ {0,0,0,0},0, \
+ /* per CPU times */ {0, }, {0, }, \
+ /* flt */ 0,0,0,0,0,0, \
+ /* swp */ 0, \
+ /* process credentials */ \
+ /* uid etc */ 0,0,0,0,0,0,0,0, \
+ /* suppl grps*/ 0, {0,}, \
+ /* caps */ CAP_INIT_EFF_SET,CAP_INIT_INH_SET,CAP_FULL_SET, \
+ /* user */ NULL, \
+ /* rlimits */ INIT_RLIMITS, \
+ /* math */ 0, \
+ /* comm */ "swapper", \
+ /* fs info */ 0,NULL, \
+ /* ipc */ NULL, NULL, \
+ /* thread */ INIT_THREAD, \
+ /* fs */ &init_fs, \
+ /* files */ &init_files, \
+ /* signals */ SPIN_LOCK_UNLOCKED, &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, 0, 0, \
+ /* exec cts */ 0,0, \
+ /* exit_sem */ __MUTEX_INITIALIZER(name.exit_sem), \
+ }
+ #else
#define INIT_TASK(name) \
/* state etc */ { 0,0,0,KERNEL_DS,&default_exec_domain,0, \
/* avg_slice */ 0, -1, \
/* counter */ DEF_PRIORITY,DEF_PRIORITY,SCHED_OTHER, \
/* mm */ NULL, &init_mm, \
***************
*** 430,439 ****
--- 479,489 ----
/* files */ &init_files, \
/* signals */ SPIN_LOCK_UNLOCKED, &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, 0, 0, \
/* exec cts */ 0,0, \
/* exit_sem */ __MUTEX_INITIALIZER(name.exit_sem), \
}
+ #endif

#ifndef INIT_TASK_SIZE
# define INIT_TASK_SIZE 2048*sizeof(long)
#endif

diff -rc5N linux-2.3.39/kernel/Makefile linux-2.3.39-hrtime/kernel/Makefile
*** linux-2.3.39/kernel/Makefile Mon Jan 10 20:15:58 2000
--- linux-2.3.39-hrtime/kernel/Makefile Tue Jan 11 13:47:39 2000
***************
*** 23,30 ****
--- 23,34 ----

ifeq ($(CONFIG_MODULES),y)
OX_OBJS += ksyms.o
endif

+ ifeq ($(CONFIG_HRTIME),y)
+ OX_OBJS += hrtime.o
+ endif
+
CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer

include $(TOPDIR)/Rules.make
diff -rc5N linux-2.3.39/kernel/exit.c linux-2.3.39-hrtime/kernel/exit.c
*** linux-2.3.39/kernel/exit.c Mon Nov 8 12:19:19 1999
--- linux-2.3.39-hrtime/kernel/exit.c Tue Jan 11 13:47:39 2000
***************
*** 43,52 ****
--- 43,75 ----

release_thread(p);
current->cmin_flt += p->min_flt + p->cmin_flt;
current->cmaj_flt += p->maj_flt + p->cmaj_flt;
current->cnswap += p->nswap + p->cnswap;
+ #ifdef CONFIG_HRTIME
+ {
+ hrtime_t t;
+ get_current_hrtime(&t);
+
+ p->hrtime->vtime += t - p->hrtime->last_dispatch;
+
+ /* see sched.c for why we set this to zero */
+ p->hrtime->last_dispatch = 0;
+ #ifdef CONFIG_HRUSTIME
+ t -= p->hrtime->last_us_dispatch;
+ if (p->hrtime->in_system)
+ p->hrtime->stime += t;
+ else
+ p->hrtime->utime += t;
+
+ /* see sched.c for why we set this to zero */
+ p->hrtime->last_us_dispatch = 0;
+ #endif
+ }
+ unref_hrtime_struct(p->hrtime);
+ p->hrtime = 0;
+ #endif
free_task_struct(p);
} else {
printk("task releasing itself\n");
}
}
***************
*** 410,419 ****
--- 433,458 ----
#endif
__exit_files(tsk);
__exit_fs(tsk);
__exit_sighand(tsk);
exit_thread();
+ #ifdef CONFIG_HRTIME
+ {
+ hrtime_t t;
+ get_current_hrtime(&t);
+
+ tsk->hrtime->vtime += t - tsk->hrtime->last_dispatch;
+
+ #ifdef CONFIG_HRUSTIME
+ t -= tsk->hrtime->last_us_dispatch;
+ if (tsk->hrtime->in_system)
+ tsk->hrtime->stime += t;
+ else
+ tsk->hrtime->utime += t;
+ #endif
+ }
+ #endif
tsk->state = TASK_ZOMBIE;
tsk->exit_code = code;
exit_notify();
task_unlock(tsk);
#ifdef DEBUG_PROC_TREE
diff -rc5N linux-2.3.39/kernel/fork.c linux-2.3.39-hrtime/kernel/fork.c
*** linux-2.3.39/kernel/fork.c Mon Dec 13 17:39:24 1999
--- linux-2.3.39-hrtime/kernel/fork.c Tue Jan 11 13:47:39 2000
***************
*** 589,598 ****
--- 589,601 ----
*/
int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
{
int retval = -ENOMEM;
struct task_struct *p;
+ #ifdef CONFIG_HRTIME
+ struct hrtime_struct *h;
+ #endif
DECLARE_MUTEX_LOCKED(sem);

if (clone_flags & CLONE_PID) {
/* This is only allowed from the boot up thread */
if (current->pid)
***************
*** 603,612 ****
--- 606,624 ----

p = alloc_task_struct();
if (!p)
goto fork_out;

+ #ifdef CONFIG_HRTIME
+ h = alloc_hrtime_struct();
+ if (!h)
+ {
+ free_task_struct(p);
+ goto fork_out;
+ }
+ #endif
+
*p = *current;

lock_kernel();

retval = -EAGAIN;
***************
*** 665,674 ****
--- 677,694 ----

p->leader = 0; /* session leadership doesn't inherit */
p->tty_old_pgrp = 0;
p->times.tms_utime = p->times.tms_stime = 0;
p->times.tms_cutime = p->times.tms_cstime = 0;
+
+ #ifdef CONFIG_HRTIME
+ p->hrtime = h;
+ /* re-zero on fork - is this the semantic that we want? */
+ init_hrtime_struct(p->hrtime);
+ ref_hrtime_struct(p->hrtime);
+ #endif
+
#ifdef __SMP__
{
int i;
p->has_cpu = 0;
p->processor = current->processor;
diff -rc5N linux-2.3.39/kernel/hrtime.c linux-2.3.39-hrtime/kernel/hrtime.c
*** linux-2.3.39/kernel/hrtime.c Wed Dec 31 19:00:00 1969
--- linux-2.3.39-hrtime/kernel/hrtime.c Tue Jan 11 13:47:39 2000
***************
*** 0 ****
--- 1,119 ----
+ /*
+ * linux/kernel/hrtime.c
+ *
+ * Copyright (C) 1999, Nick Rasmussen <nick@jive.org>
+ */
+
+ #include <linux/hrtime.h>
+ #include <linux/sched.h>
+ #include <linux/linkage.h>
+ #include <linux/mm.h>
+ #include <linux/wrapper.h>
+ #include <linux/spinlock.h>
+
+ #include <asm/hrtime.h>
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+ #include <asm/atomic.h>
+
+ #define HRTIME_DEBUG_ALLOC 0
+
+ #if HRTIME_DEBUG_ALLOC
+ static volatile atomic_t num_hrtime_structs = ATOMIC_INIT(1); /* due to init_hrtime */
+ #endif
+
+ struct hrtime_struct *alloc_hrtime_struct()
+ {
+ unsigned long page;
+
+ /* Should this be using vmalloc etc. as does drivers/char/bttv.c? */
+ struct hrtime_struct *hr = (struct hrtime_struct *) __get_free_page(GFP_KERNEL);
+ if (hr != 0)
+ {
+ page = virt_to_phys(hr);
+ mem_map_reserve(MAP_NR(__va(page)));
+ #if HRTIME_DEBUG_ALLOC
+ atomic_inc(&num_hrtime_structs);
+ printk("alloc_hrtime_struct: num_hrtime_structs are %d\n", atomic_read(&num_hrtime_structs));
+ #endif
+ }
+ return hr;
+ }
+
+ static void free_hrtime_struct(struct hrtime_struct *s)
+ {
+ unsigned long page;
+ if (s == 0)
+ return;
+
+ page = virt_to_phys(s);
+ mem_map_unreserve(MAP_NR(__va(page)));
+ free_page((unsigned long) s);
+
+ #if HRTIME_DEBUG_ALLOC
+ atomic_dec(&num_hrtime_structs);
+ printk("free_hrtime_struct: num_hrtime_structs are %d\n", atomic_read(&num_hrtime_structs));
+ #endif
+ }
+
+ void init_hrtime_struct(struct hrtime_struct *s)
+ {
+ get_current_hrtime(&s->start_time);
+
+ /* These are meaningless when CONFIG_HRUSTIME is not defined */
+ s->last_us_dispatch = s->start_time;
+ s->utime = 0;
+ s->stime = 0;
+
+ /* in_system starts out as zero since processes exiting from fork
+ * do not leave on the system call return path. */
+ s->in_system = 0;
+
+ #ifdef CONFIG_HRUSTIME
+ s->has_ustime = 1;
+ #else
+ s->has_ustime = 0;
+ #endif
+
+ s->last_dispatch = s->start_time;
+ s->vtime = 0;
+
+ /* XXX - FIXME when we do the cpu offset timings */
+ s->offset_to_cpu0 = 0;
+
+ s->refcount = 0;
+ s->reflock = SPIN_LOCK_UNLOCKED;
+ }
+
+ void ref_hrtime_struct(struct hrtime_struct *s)
+ {
+ unsigned long flags;
+
+ if (s == 0)
+ return;
+
+ spin_lock_irqsave(&s->reflock, flags);
+ s->refcount += 1;
+ spin_unlock_irqrestore(&s->reflock, flags);
+ }
+
+ void unref_hrtime_struct(struct hrtime_struct *s)
+ {
+ unsigned long flags;
+
+ if (s == 0)
+ return;
+
+ spin_lock_irqsave(&s->reflock, flags);
+ s->refcount -= 1;
+
+ if (s->refcount == 0)
+ free_hrtime_struct(s);
+
+ if (s->refcount < 0)
+ printk("unref_hrtime_struct: unreffing s@0x%08lx, "
+ "refcount %ld is now negative\n",
+ (unsigned long) s, s->refcount);
+
+ spin_unlock_irqrestore(&s->reflock, flags);
+ }
diff -rc5N linux-2.3.39/kernel/sched.c linux-2.3.39-hrtime/kernel/sched.c
*** linux-2.3.39/kernel/sched.c Sat Jan 8 15:12:22 2000
--- linux-2.3.39-hrtime/kernel/sched.c Tue Jan 11 13:47:39 2000
***************
*** 25,35 ****
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>

#include <asm/uaccess.h>
#include <asm/mmu_context.h>
!

extern void timer_bh(void);
extern void tqueue_bh(void);
extern void immediate_bh(void);

--- 25,37 ----
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>

#include <asm/uaccess.h>
#include <asm/mmu_context.h>
! #ifdef CONFIG_HRTIME
! #include <asm/hrtime.h>
! #endif

extern void timer_bh(void);
extern void tqueue_bh(void);
extern void immediate_bh(void);

***************
*** 561,570 ****
--- 563,602 ----
* rescheduled during switch_to().
*/

#endif /* __SMP__ */

+ #ifdef CONFIG_HRTIME
+ {
+ hrtime_t t;
+ get_current_hrtime(&t);
+
+ prev->hrtime->vtime += t - prev->hrtime->last_dispatch;
+
+ /* A poor man's interprocess synchronization - by overloading
+ * last_dispatch to also indicate that the process is currently
+ * executing, the spin-loop in the get_hr[usv]time to make sure
+ * that this process' hrtime_struct is self-consistent is
+ * simplified a bit. With no good way of doing atomic operations
+ * between the two processes, having last_dispatch change both
+ * when the process is swapped out and swapped in is an almost
+ * foolproof way of doing this.
+ */
+ prev->hrtime->last_dispatch = 0;
+ #ifdef CONFIG_HRUSTIME
+ t -= prev->hrtime->last_us_dispatch;
+ if (prev->hrtime->in_system)
+ prev->hrtime->stime += t;
+ else
+ prev->hrtime->utime += t;
+
+ /* ditto for last_us_dispatch */
+ prev->hrtime->last_us_dispatch = 0;
+ #endif
+ }
+ #endif
+
kstat.context_swtch++;
/*
* there are 3 processes which are affected by a context switch:
*
* prev == .... ==> (last => next)
***************
*** 596,605 ****
--- 628,647 ----
* This just switches the register state and the
* stack.
*/
switch_to(prev, next, prev);
__schedule_tail(prev);
+
+ #ifdef CONFIG_HRTIME
+ #if HRTIME_HAS_OFFSETS
+ /* XXX - FIXME - find CPU and insert offset */
+ #endif
+ get_current_hrtime(&current->hrtime->last_dispatch);
+ #ifdef CONFIG_HRUSTIME
+ get_current_hrtime(&current->hrtime->last_us_dispatch);
+ #endif
+ #endif

same_process:
reacquire_kernel_lock(current);
return;

\
 
 \ /
  Last update: 2005-03-22 13:55    [W:0.063 / U:0.124 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site