2002-10-15 05:57:41

by Robert Love

[permalink] [raw]
Subject: [PATCH] 2.4: variable HZ

I backported the jiffies_to_clock_t() code from 2.5 to 2.4, mostly just
for fun.

It works fine, and I have successfully used HZ=1000 on my machines. It
is the same API as 2.5, used in the same places - we export a static
HZ=100 to user-space and convert from the real HZ as needed. The only
difference is I added a CONFIG_HZ to allow the user to set the value.

There are probably some HZ values you cannot use due to NTP issues. I
suggest HZ=1000, since I know that works, and 2.5 is using it. RedHat
is supposedly shipping their kernel with HZ=512 but I do not know if
they did anything else special.

Oh, and I did not backport 64-bit jiffies yet. So HZ=1000 will wrap
around in just under 50 days. If you just cannot have that, stick with
a lower value.

Patch is against 2.4.20-pre10-ac2 but applies OK to all 2.4.20-pre and
2.4.19 kernels.

Enjoy,

Robert Love

diff -urN linux-2.4.20-pre10-ac2/arch/i386/config.in linux/arch/i386/config.in
--- linux-2.4.20-pre10-ac2/arch/i386/config.in 2002-10-14 01:43:05.000000000 -0400
+++ linux/arch/i386/config.in 2002-10-14 18:24:48.000000000 -0400
@@ -244,6 +244,7 @@
mainmenu_option next_comment
comment 'General setup'

+int 'Timer frequency (HZ) (100)' CONFIG_HZ 100
bool 'Networking support' CONFIG_NET

# Visual Workstation support is utterly broken.
diff -urN linux-2.4.20-pre10-ac2/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.20-pre10-ac2/Documentation/Configure.help 2002-10-14 01:43:06.000000000 -0400
+++ linux/Documentation/Configure.help 2002-10-14 18:32:38.000000000 -0400
@@ -2411,6 +2411,18 @@
behaviour is platform-dependent, but normally the flash frequency is
a hyperbolic function of the 5-minute load average.

+Timer frequency
+CONFIG_HZ
+ The frequency the system timer interrupt pops. Higher tick values provide
+ improved granularity of timers, improved select() and poll() performance,
+ and lower scheduling latency. Higher values, however, increase interrupt
+ overhead and will allow jiffie wraparound sooner. For compatibility, the
+ tick count is always exported as if HZ=100.
+
+ The default value, which was the value for all of eternity, is 100. If
+ you are looking to provide better timer granularity or increased desktop
+ performance, try 500 or 1000. In unsure, go with the default of 100.
+
Networking support
CONFIG_NET
Unless you really know what you are doing, you should say Y here.
diff -urN linux-2.4.20-pre10-ac2/fs/proc/array.c linux/fs/proc/array.c
--- linux-2.4.20-pre10-ac2/fs/proc/array.c 2002-10-14 01:43:10.000000000 -0400
+++ linux/fs/proc/array.c 2002-10-14 18:24:48.000000000 -0400
@@ -360,15 +360,15 @@
task->cmin_flt,
task->maj_flt,
task->cmaj_flt,
- task->times.tms_utime,
- task->times.tms_stime,
- task->times.tms_cutime,
- task->times.tms_cstime,
+ jiffies_to_clock_t(task->times.tms_utime),
+ jiffies_to_clock_t(task->times.tms_stime),
+ jiffies_to_clock_t(task->times.tms_cutime),
+ jiffies_to_clock_t(task->times.tms_cstime),
priority,
nice,
0UL /* removed */,
- task->it_real_value,
- task->start_time,
+ jiffies_to_clock_t(task->it_real_value),
+ jiffies_to_clock_t(task->start_time),
vsize,
mm ? mm->rss : 0, /* you might want to shift this left 3 */
task->rlim[RLIMIT_RSS].rlim_cur,
@@ -686,14 +686,14 @@

len = sprintf(buffer,
"cpu %lu %lu\n",
- task->times.tms_utime,
- task->times.tms_stime);
+ jiffies_to_clock_t(task->times.tms_utime),
+ jiffies_to_clock_t(task->times.tms_stime));

for (i = 0 ; i < smp_num_cpus; i++)
len += sprintf(buffer + len, "cpu%d %lu %lu\n",
i,
- task->per_cpu_utime[cpu_logical_map(i)],
- task->per_cpu_stime[cpu_logical_map(i)]);
+ jiffies_to_clock_t(task->per_cpu_utime[cpu_logical_map(i)]),
+ jiffies_to_clock_t(task->per_cpu_stime[cpu_logical_map(i)]));

return len;
}
diff -urN linux-2.4.20-pre10-ac2/fs/proc/proc_misc.c linux/fs/proc/proc_misc.c
--- linux-2.4.20-pre10-ac2/fs/proc/proc_misc.c 2002-10-14 01:43:10.000000000 -0400
+++ linux/fs/proc/proc_misc.c 2002-10-14 18:40:08.000000000 -0400
@@ -317,7 +317,7 @@
{
int i, len = 0;
extern unsigned long total_forks;
- unsigned long jif = jiffies;
+ unsigned long jif = jiffies_to_clock_t(jiffies);
unsigned int sum = 0, user = 0, nice = 0, system = 0;
int major, disk;

@@ -334,16 +334,19 @@
}

proc_sprintf(page, &off, &len,
- "cpu %u %u %u %lu\n", user, nice, system,
+ "cpu %u %u %u %lu\n",
+ jiffies_to_clock_t(user),
+ jiffies_to_clock_t(nice),
+ jiffies_to_clock_t(system),
jif * smp_num_cpus - (user + nice + system));
for (i = 0 ; i < smp_num_cpus; i++)
proc_sprintf(page, &off, &len,
"cpu%d %u %u %u %lu\n",
i,
- kstat.per_cpu_user[cpu_logical_map(i)],
- kstat.per_cpu_nice[cpu_logical_map(i)],
- kstat.per_cpu_system[cpu_logical_map(i)],
- jif - ( kstat.per_cpu_user[cpu_logical_map(i)] \
+ jiffies_to_clock_t(kstat.per_cpu_user[cpu_logical_map(i)]),
+ jiffies_to_clock_t(kstat.per_cpu_nice[cpu_logical_map(i)]),
+ jiffies_to_clock_t(kstat.per_cpu_system[cpu_logical_map(i)]),
+ jif - jiffies_to_clock_t(kstat.per_cpu_user[cpu_logical_map(i)] \
+ kstat.per_cpu_nice[cpu_logical_map(i)] \
+ kstat.per_cpu_system[cpu_logical_map(i)]));
proc_sprintf(page, &off, &len,
diff -urN linux-2.4.20-pre10-ac2/include/asm-i386/param.h linux/include/asm-i386/param.h
--- linux-2.4.20-pre10-ac2/include/asm-i386/param.h 2002-10-14 01:33:16.000000000 -0400
+++ linux/include/asm-i386/param.h 2002-10-14 18:33:35.000000000 -0400
@@ -1,8 +1,17 @@
#ifndef _ASMi386_PARAM_H
#define _ASMi386_PARAM_H

+#include <linux/config.h>
+
+#ifdef __KERNEL__
+# define HZ CONFIG_HZ /* internal kernel timer frequency */
+# define USER_HZ 100 /* some user interfaces are in ticks */
+# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
+# define jiffies_to_clock_t(x) ((x) / ((HZ) / (USER_HZ)))
+#endif
+
#ifndef HZ
-#define HZ 100
+#define HZ 100 /* if userspace cheats, give them 100 */
#endif

#define EXEC_PAGESIZE 4096
@@ -17,8 +26,4 @@

#define MAXHOSTNAMELEN 64 /* max length of hostname */

-#ifdef __KERNEL__
-# define CLOCKS_PER_SEC 100 /* frequency at which times() counts */
-#endif
-
#endif
diff -urN linux-2.4.20-pre10-ac2/kernel/signal.c linux/kernel/signal.c
--- linux-2.4.20-pre10-ac2/kernel/signal.c 2002-10-14 01:43:11.000000000 -0400
+++ linux/kernel/signal.c 2002-10-14 18:24:49.000000000 -0400
@@ -13,7 +13,7 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/sched.h>
-
+#include <asm/param.h>
#include <asm/uaccess.h>

/*
@@ -775,8 +775,8 @@
info.si_uid = tsk->uid;

/* FIXME: find out whether or not this is supposed to be c*time. */
- info.si_utime = tsk->times.tms_utime;
- info.si_stime = tsk->times.tms_stime;
+ info.si_utime = jiffies_to_clock_t(tsk->times.tms_utime);
+ info.si_stime = jiffies_to_clock_t(tsk->times.tms_stime);

status = tsk->exit_code & 0x7f;
why = SI_KERNEL; /* shouldn't happen */
diff -urN linux-2.4.20-pre10-ac2/kernel/sys.c linux/kernel/sys.c
--- linux-2.4.20-pre10-ac2/kernel/sys.c 2002-10-14 01:43:11.000000000 -0400
+++ linux/kernel/sys.c 2002-10-14 18:24:49.000000000 -0400
@@ -15,7 +15,7 @@
#include <linux/prctl.h>
#include <linux/init.h>
#include <linux/highuid.h>
-
+#include <asm/param.h>
#include <asm/uaccess.h>
#include <asm/io.h>

@@ -792,16 +792,23 @@

asmlinkage long sys_times(struct tms * tbuf)
{
+ struct tms temp;
+
/*
* In the SMP world we might just be unlucky and have one of
* the times increment as we use it. Since the value is an
* atomically safe type this is just fine. Conceptually its
* as if the syscall took an instant longer to occur.
*/
- if (tbuf)
- if (copy_to_user(tbuf, &current->times, sizeof(struct tms)))
+ if (tbuf) {
+ temp.tms_utime = jiffies_to_clock_t(current->times.tms_utime);
+ temp.tms_stime = jiffies_to_clock_t(current->times.tms_stime);
+ temp.tms_cutime = jiffies_to_clock_t(current->times.tms_cutime);
+ temp.tms_cstime = jiffies_to_clock_t(current->times.tms_cstime);
+ if (copy_to_user(tbuf, &temp, sizeof(struct tms)))
return -EFAULT;
- return jiffies;
+ }
+ return jiffies_to_clock_t(jiffies);
}

/*




2002-10-15 06:44:51

by Robert Love

[permalink] [raw]
Subject: Re: [PATCH] 2.4: variable HZ

On Tue, 2002-10-15 at 02:03, Robert Love wrote:

> It works fine, and I have successfully used HZ=1000 on my machines.

Except processor usage output was screwy.

Attached is an updated patch which fixes the problem.

Robert Love

diff -urN linux-2.4.20-pre10-ac2/arch/i386/config.in linux/arch/i386/config.in
--- linux-2.4.20-pre10-ac2/arch/i386/config.in 2002-10-14 01:43:05.000000000 -0400
+++ linux/arch/i386/config.in 2002-10-15 02:41:39.000000000 -0400
@@ -244,6 +244,7 @@
mainmenu_option next_comment
comment 'General setup'

+int 'Timer frequency (HZ) (100)' CONFIG_HZ 100
bool 'Networking support' CONFIG_NET

# Visual Workstation support is utterly broken.
diff -urN linux-2.4.20-pre10-ac2/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.20-pre10-ac2/Documentation/Configure.help 2002-10-14 01:43:06.000000000 -0400
+++ linux/Documentation/Configure.help 2002-10-15 02:41:40.000000000 -0400
@@ -2411,6 +2411,18 @@
behaviour is platform-dependent, but normally the flash frequency is
a hyperbolic function of the 5-minute load average.

+Timer frequency
+CONFIG_HZ
+ The frequency the system timer interrupt pops. Higher tick values provide
+ improved granularity of timers, improved select() and poll() performance,
+ and lower scheduling latency. Higher values, however, increase interrupt
+ overhead and will allow jiffie wraparound sooner. For compatibility, the
+ tick count is always exported as if HZ=100.
+
+ The default value, which was the value for all of eternity, is 100. If
+ you are looking to provide better timer granularity or increased desktop
+ performance, try 500 or 1000. In unsure, go with the default of 100.
+
Networking support
CONFIG_NET
Unless you really know what you are doing, you should say Y here.
diff -urN linux-2.4.20-pre10-ac2/fs/proc/array.c linux/fs/proc/array.c
--- linux-2.4.20-pre10-ac2/fs/proc/array.c 2002-10-14 01:43:10.000000000 -0400
+++ linux/fs/proc/array.c 2002-10-14 18:24:48.000000000 -0400
@@ -360,15 +360,15 @@
task->cmin_flt,
task->maj_flt,
task->cmaj_flt,
- task->times.tms_utime,
- task->times.tms_stime,
- task->times.tms_cutime,
- task->times.tms_cstime,
+ jiffies_to_clock_t(task->times.tms_utime),
+ jiffies_to_clock_t(task->times.tms_stime),
+ jiffies_to_clock_t(task->times.tms_cutime),
+ jiffies_to_clock_t(task->times.tms_cstime),
priority,
nice,
0UL /* removed */,
- task->it_real_value,
- task->start_time,
+ jiffies_to_clock_t(task->it_real_value),
+ jiffies_to_clock_t(task->start_time),
vsize,
mm ? mm->rss : 0, /* you might want to shift this left 3 */
task->rlim[RLIMIT_RSS].rlim_cur,
@@ -686,14 +686,14 @@

len = sprintf(buffer,
"cpu %lu %lu\n",
- task->times.tms_utime,
- task->times.tms_stime);
+ jiffies_to_clock_t(task->times.tms_utime),
+ jiffies_to_clock_t(task->times.tms_stime));

for (i = 0 ; i < smp_num_cpus; i++)
len += sprintf(buffer + len, "cpu%d %lu %lu\n",
i,
- task->per_cpu_utime[cpu_logical_map(i)],
- task->per_cpu_stime[cpu_logical_map(i)]);
+ jiffies_to_clock_t(task->per_cpu_utime[cpu_logical_map(i)]),
+ jiffies_to_clock_t(task->per_cpu_stime[cpu_logical_map(i)]));

return len;
}
diff -urN linux-2.4.20-pre10-ac2/fs/proc/proc_misc.c linux/fs/proc/proc_misc.c
--- linux-2.4.20-pre10-ac2/fs/proc/proc_misc.c 2002-10-14 01:43:10.000000000 -0400
+++ linux/fs/proc/proc_misc.c 2002-10-15 02:29:21.000000000 -0400
@@ -317,16 +317,16 @@
{
int i, len = 0;
extern unsigned long total_forks;
- unsigned long jif = jiffies;
+ unsigned long jif = jiffies_to_clock_t(jiffies);
unsigned int sum = 0, user = 0, nice = 0, system = 0;
int major, disk;

for (i = 0 ; i < smp_num_cpus; i++) {
int cpu = cpu_logical_map(i), j;

- user += kstat.per_cpu_user[cpu];
- nice += kstat.per_cpu_nice[cpu];
- system += kstat.per_cpu_system[cpu];
+ user += jiffies_to_clock_t(kstat.per_cpu_user[cpu]);
+ nice += jiffies_to_clock_t(kstat.per_cpu_nice[cpu]);
+ system += jiffies_to_clock_t(kstat.per_cpu_system[cpu]);
#if !defined(CONFIG_ARCH_S390)
for (j = 0 ; j < NR_IRQS ; j++)
sum += kstat.irqs[cpu][j];
@@ -340,10 +340,10 @@
proc_sprintf(page, &off, &len,
"cpu%d %u %u %u %lu\n",
i,
- kstat.per_cpu_user[cpu_logical_map(i)],
- kstat.per_cpu_nice[cpu_logical_map(i)],
- kstat.per_cpu_system[cpu_logical_map(i)],
- jif - ( kstat.per_cpu_user[cpu_logical_map(i)] \
+ jiffies_to_clock_t(kstat.per_cpu_user[cpu_logical_map(i)]),
+ jiffies_to_clock_t(kstat.per_cpu_nice[cpu_logical_map(i)]),
+ jiffies_to_clock_t(kstat.per_cpu_system[cpu_logical_map(i)]),
+ jif - jiffies_to_clock_t(kstat.per_cpu_user[cpu_logical_map(i)] \
+ kstat.per_cpu_nice[cpu_logical_map(i)] \
+ kstat.per_cpu_system[cpu_logical_map(i)]));
proc_sprintf(page, &off, &len,
diff -urN linux-2.4.20-pre10-ac2/include/asm-i386/param.h linux/include/asm-i386/param.h
--- linux-2.4.20-pre10-ac2/include/asm-i386/param.h 2002-10-14 01:33:16.000000000 -0400
+++ linux/include/asm-i386/param.h 2002-10-14 18:46:32.000000000 -0400
@@ -1,8 +1,17 @@
#ifndef _ASMi386_PARAM_H
#define _ASMi386_PARAM_H

+#include <linux/config.h>
+
+#ifdef __KERNEL__
+# define HZ CONFIG_HZ /* internal kernel timer frequency */
+# define USER_HZ 100 /* some user interfaces are in ticks */
+# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
+# define jiffies_to_clock_t(x) ((x) / ((HZ) / (USER_HZ)))
+#endif
+
#ifndef HZ
-#define HZ 100
+#define HZ 100 /* if userspace cheats, give them 100 */
#endif

#define EXEC_PAGESIZE 4096
@@ -17,8 +26,4 @@

#define MAXHOSTNAMELEN 64 /* max length of hostname */

-#ifdef __KERNEL__
-# define CLOCKS_PER_SEC 100 /* frequency at which times() counts */
-#endif
-
#endif
diff -urN linux-2.4.20-pre10-ac2/kernel/signal.c linux/kernel/signal.c
--- linux-2.4.20-pre10-ac2/kernel/signal.c 2002-10-14 01:43:11.000000000 -0400
+++ linux/kernel/signal.c 2002-10-14 18:24:49.000000000 -0400
@@ -13,7 +13,7 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/sched.h>
-
+#include <asm/param.h>
#include <asm/uaccess.h>

/*
@@ -775,8 +775,8 @@
info.si_uid = tsk->uid;

/* FIXME: find out whether or not this is supposed to be c*time. */
- info.si_utime = tsk->times.tms_utime;
- info.si_stime = tsk->times.tms_stime;
+ info.si_utime = jiffies_to_clock_t(tsk->times.tms_utime);
+ info.si_stime = jiffies_to_clock_t(tsk->times.tms_stime);

status = tsk->exit_code & 0x7f;
why = SI_KERNEL; /* shouldn't happen */
diff -urN linux-2.4.20-pre10-ac2/kernel/sys.c linux/kernel/sys.c
--- linux-2.4.20-pre10-ac2/kernel/sys.c 2002-10-14 01:43:11.000000000 -0400
+++ linux/kernel/sys.c 2002-10-14 18:24:49.000000000 -0400
@@ -15,7 +15,7 @@
#include <linux/prctl.h>
#include <linux/init.h>
#include <linux/highuid.h>
-
+#include <asm/param.h>
#include <asm/uaccess.h>
#include <asm/io.h>

@@ -792,16 +792,23 @@

asmlinkage long sys_times(struct tms * tbuf)
{
+ struct tms temp;
+
/*
* In the SMP world we might just be unlucky and have one of
* the times increment as we use it. Since the value is an
* atomically safe type this is just fine. Conceptually its
* as if the syscall took an instant longer to occur.
*/
- if (tbuf)
- if (copy_to_user(tbuf, &current->times, sizeof(struct tms)))
+ if (tbuf) {
+ temp.tms_utime = jiffies_to_clock_t(current->times.tms_utime);
+ temp.tms_stime = jiffies_to_clock_t(current->times.tms_stime);
+ temp.tms_cutime = jiffies_to_clock_t(current->times.tms_cutime);
+ temp.tms_cstime = jiffies_to_clock_t(current->times.tms_cstime);
+ if (copy_to_user(tbuf, &temp, sizeof(struct tms)))
return -EFAULT;
- return jiffies;
+ }
+ return jiffies_to_clock_t(jiffies);
}

/*

2002-10-16 12:05:11

by Roy Sigurd Karlsbakk

[permalink] [raw]
Subject: Re: [PATCH] 2.4: variable HZ (broken?)

On Tuesday 15 October 2002 08:50, Robert Love wrote:
> On Tue, 2002-10-15 at 02:03, Robert Love wrote:
> > It works fine, and I have successfully used HZ=1000 on my machines.
>
> Except processor usage output was screwy.
>

and except that it somehow breaks compiling serial.c?

gcc -D__KERNEL__ -I/usr/src/prontux-0.1.9/include -Wall -Wstrict-prototypes
-Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer
-pipe -mpreferred-stack-boundary=2 -march=i586 -nostdinc -iwithprefix
include -DKBUILD_BASENAME=serial -c -o serial.o serial.c
serial.c:231:27: serial_compat.h: No such file or directory
serial.c: In function `receive_chars':
serial.c:677: warning: implicit declaration of function `queue_task_irq_off'
serial.c: At top level:
serial.c:1591: warning: static declaration for `tty_get_baud_rate' follows
non-static
serial.c: In function `rs_write':
serial.c:1879: warning: implicit declaration of function `copy_from_user'
serial.c: In function `get_serial_info':
serial.c:2077: warning: implicit declaration of function `copy_to_user'
serial.c: In function `send_break':
serial.c:2391: structure has no member named `timeout'
serial.c:3843:32: linux/symtab_begin.h: No such file or directory
serial.c:3846:30: linux/symtab_end.h: No such file or directory
serial.c: At top level:
serial.c:3842: variable `serial_syms' has initializer but incomplete type
serial.c:3844: warning: implicit declaration of function `X'
serial.c:3844: warning: excess elements in struct initializer
serial.c:3844: warning: (near initialization for `serial_syms')
serial.c:3845: warning: excess elements in struct initializer
serial.c:3845: warning: (near initialization for `serial_syms')
serial.c:3331: warning: `rs_read_proc' defined but not used
serial.c:3842: warning: `serial_syms' defined but not used
make[3]: *** [serial.o] Error 1
make[3]: Leaving directory `/usr/src/prontux-0.1.9/drivers/char'
make[2]: *** [first_rule] Error 2
make[2]: Leaving directory `/usr/src/prontux-0.1.9/drivers/char'
make[1]: *** [_subdir_char] Error 2
make[1]: Leaving directory `/usr/src/prontux-0.1.9/drivers'
make: *** [_dir_drivers] Error 2


--
Roy Sigurd Karlsbakk, Datavaktmester
ProntoTV AS - http://www.pronto.tv/
Tel: +47 9801 3356

Computers are like air conditioners.
They stop working when you open Windows.

2002-10-16 12:15:34

by Roy Sigurd Karlsbakk

[permalink] [raw]
Subject: Re: [PATCH] 2.4: variable HZ (not broken. My fault)

sorry
this was my fault
was playing around with version numbers

On Wednesday 16 October 2002 14:14, Roy Sigurd Karlsbakk wrote:
> On Tuesday 15 October 2002 08:50, Robert Love wrote:
> > On Tue, 2002-10-15 at 02:03, Robert Love wrote:
> > > It works fine, and I have successfully used HZ=1000 on my machines.
> >
> > Except processor usage output was screwy.
>
> and except that it somehow breaks compiling serial.c?
>
> gcc -D__KERNEL__ -I/usr/src/prontux-0.1.9/include -Wall -Wstrict-prototypes
> -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer
> -pipe -mpreferred-stack-boundary=2 -march=i586 -nostdinc -iwithprefix
> include -DKBUILD_BASENAME=serial -c -o serial.o serial.c
> serial.c:231:27: serial_compat.h: No such file or directory
> serial.c: In function `receive_chars':
> serial.c:677: warning: implicit declaration of function
> `queue_task_irq_off' serial.c: At top level:
> serial.c:1591: warning: static declaration for `tty_get_baud_rate' follows
> non-static
> serial.c: In function `rs_write':
> serial.c:1879: warning: implicit declaration of function `copy_from_user'
> serial.c: In function `get_serial_info':
> serial.c:2077: warning: implicit declaration of function `copy_to_user'
> serial.c: In function `send_break':
> serial.c:2391: structure has no member named `timeout'
> serial.c:3843:32: linux/symtab_begin.h: No such file or directory
> serial.c:3846:30: linux/symtab_end.h: No such file or directory
> serial.c: At top level:
> serial.c:3842: variable `serial_syms' has initializer but incomplete type
> serial.c:3844: warning: implicit declaration of function `X'
> serial.c:3844: warning: excess elements in struct initializer
> serial.c:3844: warning: (near initialization for `serial_syms')
> serial.c:3845: warning: excess elements in struct initializer
> serial.c:3845: warning: (near initialization for `serial_syms')
> serial.c:3331: warning: `rs_read_proc' defined but not used
> serial.c:3842: warning: `serial_syms' defined but not used
> make[3]: *** [serial.o] Error 1
> make[3]: Leaving directory `/usr/src/prontux-0.1.9/drivers/char'
> make[2]: *** [first_rule] Error 2
> make[2]: Leaving directory `/usr/src/prontux-0.1.9/drivers/char'
> make[1]: *** [_subdir_char] Error 2
> make[1]: Leaving directory `/usr/src/prontux-0.1.9/drivers'
> make: *** [_dir_drivers] Error 2

--
Roy Sigurd Karlsbakk, Datavaktmester
ProntoTV AS - http://www.pronto.tv/
Tel: +47 9801 3356

Computers are like air conditioners.
They stop working when you open Windows.

2002-10-18 11:42:11

by Neil Conway

[permalink] [raw]
Subject: Re: [PATCH] 2.4: variable HZ

Hiya... Nice patch, must try it when I find a few minutes - I think I
have a few apps that are limited by select/poll behaviour.

I was looking at your jiffies_to_clock_t() macro, and I notice that it
will screw up badly if the user chooses a HZ value that isn't a multiple
of the normal value (e.g. 1000 is OK, 512 isn't).

How about tweaking the macro a little? Instead of:
x / (HZ/USER_HZ)
you could use:
(x/HZ*USER_HZ + x%HZ*USER_HZ/HZ)

which minimises roundoff error and also won't overflow (at least, it
won't overflow as long as HZ*USER_HZ doesn't overflow!).

You could even use both versions of the macro, choosing between them at
compile time depending on whether or not (HZ % USER_HZ == 0).

What do you think?

cheers
Neil
PS: I'm off-list.

2002-10-18 18:21:41

by Tim Schmielau

[permalink] [raw]
Subject: Re: [PATCH] 2.4: variable HZ

On 15 Oct 2002, Robert Love wrote:
> I backported the jiffies_to_clock_t() code from 2.5 to 2.4, mostly just
> for fun.
...
> Oh, and I did not backport 64-bit jiffies yet.

If you would, how would you call the analogous function for 64 bit values?
And the type it returns?

The patches to make the kernel interfaces use the 64 bit jiffies value sit
in Davej's tree since around 2.5.20-dj3, just waiting for the answer to
these questions.

jiffies_64_to_clock_t_64() seems a bit lengthy. My current personal
favourite would be jiffies_64_to_user_HZ(), just returning an u64, so that
we don't keep on inventing silly types that get used just a very few
times.

Just my 0.02 euro, though.

Tim

2002-10-18 18:38:10

by Robert Love

[permalink] [raw]
Subject: Re: [PATCH] 2.4: variable HZ

On Fri, 2002-10-18 at 07:51, Neil Conway wrote:

> I was looking at your jiffies_to_clock_t() macro, and I notice that it
> will screw up badly if the user chooses a HZ value that isn't a multiple
> of the normal value (e.g. 1000 is OK, 512 isn't).

OK, sure, but why specify a power-of-two HZ? There is absolutely no
reason to, at least on x86.

Want 512? 500 will do just as well and has the benefit of (a) being a
multiple of the previous HZ and (b) evenly dividing into our concept of
time.

Robert Love

2002-10-18 19:32:46

by Richard B. Johnson

[permalink] [raw]
Subject: Re: [PATCH] 2.4: variable HZ

On 18 Oct 2002, Robert Love wrote:

> On Fri, 2002-10-18 at 07:51, Neil Conway wrote:
>
> > I was looking at your jiffies_to_clock_t() macro, and I notice that it
> > will screw up badly if the user chooses a HZ value that isn't a multiple
> > of the normal value (e.g. 1000 is OK, 512 isn't).
>
> OK, sure, but why specify a power-of-two HZ? There is absolutely no
> reason to, at least on x86.
>
> Want 512? 500 will do just as well and has the benefit of (a) being a
> multiple of the previous HZ and (b) evenly dividing into our concept of
> time.
>
> Robert Love
>

At least on ix86, HZ needs to be something that CLOCK_TICK_RATE/LATCH
comes out fairly close. Remember, LATCH is the divisor for the PIT
and that PIT gets CLOCK_TICK_RATE for its input. If this number isn't
fairly 'exact' there will be much jumping of time in the sawtooth
corrector.

If you are not using ELAN, CLOCK_TICK_RATE is 1193180. If your HZ is
100, you have 1193180/100 = 1193.18, not too exact. if you use
500, you get 1193180/500 = 2386.36 which has twice as much round-off.
If you use 1193180/512 = 2330.43, even a higher fractional part.

Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
The US military has given us many words, FUBAR, SNAFU, now ENRON.
Yes, top management were graduates of West Point and Annapolis.

2002-10-19 06:58:11

by jdow

[permalink] [raw]
Subject: Re: [PATCH] 2.4: variable HZ

Richard, would you believe that this is essentially what is done with the
GPS satellites in the dither process and in the clock correction process
to make the drifty Rb standards as stable as ground standards?

(You'd better. I designed the beastie involved.)
{^_-} Joanne, [email protected]
----- Original Message -----
From: "Richard B. Johnson" <[email protected]>
To: "Robert Love" <[email protected]>
Cc: "Neil Conway" <[email protected]>; <[email protected]>
Sent: Friday, October 18, 2002 12:38
Subject: Re: [PATCH] 2.4: variable HZ


> On 18 Oct 2002, Robert Love wrote:
>
> > On Fri, 2002-10-18 at 07:51, Neil Conway wrote:
> >
> > > I was looking at your jiffies_to_clock_t() macro, and I notice that it
> > > will screw up badly if the user chooses a HZ value that isn't a multiple
> > > of the normal value (e.g. 1000 is OK, 512 isn't).
> >
> > OK, sure, but why specify a power-of-two HZ? There is absolutely no
> > reason to, at least on x86.
> >
> > Want 512? 500 will do just as well and has the benefit of (a) being a
> > multiple of the previous HZ and (b) evenly dividing into our concept of
> > time.
> >
> > Robert Love
> >
>
> At least on ix86, HZ needs to be something that CLOCK_TICK_RATE/LATCH
> comes out fairly close. Remember, LATCH is the divisor for the PIT
> and that PIT gets CLOCK_TICK_RATE for its input. If this number isn't
> fairly 'exact' there will be much jumping of time in the sawtooth
> corrector.
>
> If you are not using ELAN, CLOCK_TICK_RATE is 1193180. If your HZ is
> 100, you have 1193180/100 = 1193.18, not too exact. if you use
> 500, you get 1193180/500 = 2386.36 which has twice as much round-off.
> If you use 1193180/512 = 2330.43, even a higher fractional part.
>
> Cheers,
> Dick Johnson
> Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
> The US military has given us many words, FUBAR, SNAFU, now ENRON.
> Yes, top management were graduates of West Point and Annapolis.
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/

2002-10-19 09:30:29

by Willy Tarreau

[permalink] [raw]
Subject: Re: [PATCH] 2.4: variable HZ

On Fri, Oct 18, 2002 at 03:38:43PM -0400, Richard B. Johnson wrote:
> If you are not using ELAN, CLOCK_TICK_RATE is 1193180.

well, in fact it's 1193181.666... (14318180/12).

> If your HZ is 100, you have 1193180/100 = 1193.18, not too exact.

you meant 1000, I suppose ?

> if you use 500, you get 1193180/500 = 2386.36 which has twice as much
> round-off. If you use 1193180/512 = 2330.43, even a higher fractional
> part.

those interested can try 511 Hz (/2334.994) or 1900 Hz (/627.990) which
has the double advantage of being multiple of 100 Hz and have a little
drift due to frac part (/628 gives 1899.97 Hz, and /627 gives 1903.001 Hz).
If you don't need a multiple of 100 Hz, I noticed that dividing by 5709
gives 209.0001 Hz.

I'm also wondering why we never use the RTC as an interrupt source. Are
there any incompatible PCs ?

Cheers,
Willy

2002-10-21 08:05:57

by Neil Conway

[permalink] [raw]
Subject: Re: [PATCH] 2.4: variable HZ

Robert Love wrote:
> OK, sure, but why specify a power-of-two HZ? There is absolutely no
> reason to, at least on x86.

Totally agree. However, I wasn't restricting it to powers of two. You
just happened to have mentioned 512 (wrt. RedHat).

> Want 512? 500 will do just as well and has the benefit of (a) being a
> multiple of the previous HZ and (b) evenly dividing into our concept of
> time.

512 ~= 500. 150 !~= 100. Would someone want to use 150? Maybe...

Anyway, it's no big deal if you prefer to leave your patch as-is.
However, if you do, then you need to at least add a comment to the code
and modify the Configure.help to make it clear that only integer
multiples work properly. In fact, you could just make the HZ Config
value be a "speed-up ratio" which would make various bits of the patch
cleaner.

Neil

2002-10-21 13:06:33

by Richard B. Johnson

[permalink] [raw]
Subject: Re: [PATCH] 2.4: variable HZ

On Sat, 19 Oct 2002, jdow wrote:

> Richard, would you believe that this is essentially what is done with the
> GPS satellites in the dither process and in the clock correction process
> to make the drifty Rb standards as stable as ground standards?
>
> (You'd better. I designed the beastie involved.)
> {^_-} Joanne, [email protected]

Sure. I helped develop a Kalman Filter that would run in real-time.
It was first implemented in Matlab (which is awful to interpret).
I rewrote it in ix86 assembly, using synthetic division (where you
save the remainder and use it in a subsequent division for the same
element in the polynomial). The result being that the filter generates
no error even though it performs multiple divisions of non-integral
numbers.

These techniques are great for continuous functions. Early filtering
techniques, using classical methods (average, r.m.s, r.s.s, etc.)
develop a bias because of round-off. The synthetic division bounds
the bias to one less than the last divisor.

If you filter enough stuff, over a long enough time, you can make
gold out of shit. The onboard GPS software has a very long time
to tune. Its a good candidate. In principle, the ground standard
doesn't have to be very good as long as it averages correctly
with low residual bias.

Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
The US military has given us many words, FUBAR, SNAFU, now ENRON.
Yes, top management were graduates of West Point and Annapolis.