How does USER_HZ solve the jiffy scaling issue?

linux, linux-kernel

Solution

`USER_HZ` was implemented as a compromise: although user code could have a hard-coded value different from `USER_HZ`, the Linux kernel historically had a `HZ` value of 100 -- so virtually all hard-coded `HZ` values in existing user code had been set to 100.

Here's the essence of what happened:

The Linux kernel used to have HZ set at a constant 100 for all
architectures. As additional architecture support was added, the HZ
value became variable: e.g. Linux on one machine could have a HZ
value of 1000 while Linux on another machine could have a HZ value
of 100.

This possibility of a variable HZ value caused existing user code,
which had hardcoded an expectation of HZ set to 100, to break due to
the exposure in userspace of kernel jiffies which may have be based
on a HZ value that was not equal to 100.

To prevent the chaos that would occur from years of existing user
code hardcoding a constant HZ value of 100, a compromise was made:
any exposure of kernel jiffies to userspace should be scaled via a
new USER_HZ value -- thus preventing existing user code from
breaking on machines with a different HZ value, while still allowing
the kernel on those machines to have a HZ value different from the
historic 100 value.

Now, this leaves the question of why some kernel jiffies are exposed to userspace unscaled (e.g. in `/proc/timer_list`). Thomas Gleixner explains:

All instances which are de facto APIs, syscalls and also various files in proc/ must be in USER_HZ because userspace applications depend on the USER_HZ value.

proc/timer_list is exempt from that because its more a debugging interface which is not part of the strict kernel API. And we really want to see the real values and not the scaled USER_HZ ones for that purpose. I hope that answers your question.

So all instances which are part of the strict kernel API are meant to scale kernel jiffies via `USER_HZ` before exposure to userspace, which other instances are exempt.

See also

The Tick Rate: HZ section of Linux Kernel Development Second Edition by Robert Love

Problem

As I understand, the `USER_HZ` constant was added in Linux 2.6 to solve the issues arising from the expectations of the `HZ` value in user-space: in previous versions of Linux, changing the `HZ` value may cause values in user-space applications to be unintentionally scaled. I'm confused about how the `USER_HZ` constant solves this scaling problem. For example, say a user-space application converts jiffies to seconds: ``` long MY_HZ = sysconf(_SC_CLK_TCK); /* num_jiffies acquired from /proc but * simplified to 1000 here for clarity */ long num_jiffies = 1000; long num_seconds = num_jiffies / MY_HZ; ``` Since the user-space application is determining the `HZ` value via a `sysconf` call, wouldn't this prevent a scaling issue? If on the other hand, the user-space applications did have the `HZ` value hard-coded into their source, how would a `USER_HZ` constant prevent a scaling issue -- the user-space applications would be using their hard-coded constants rather than the system's `USER_HZ`, and there's no guarantee the hard-coded constants matches `USER_HZ`? Furthermore, are all clock tick values available to user-space (e.g. `/proc`) already scaled to `USER_HZ`? How does a user-space program know whether a value in jiffies is scaled to `HZ` or `USER_HZ`?

Original source