Re: How to read a timestamp in kernel driver code?

From: Riley Williams (rhw@MemAlpha.cx)
Date: Sun Feb 27 2000 - 05:46:05 EST


Hi Mike, Alan.

ALAN: I'm not quite sure about the ease with which the jiffies
interval can be changed in current kernels. Memory says you're
reasonably au fait with that, so can you advise on the current
state of play please?

>>> Correct. All I need to know is how many "X" units of
>>> time have expired between keycode Y's down event, and
>>> its up event. The time units are irrelevant -
>>> microseconds, nanoseconds, jiffies, whatever ... and
>>> todays date is certainly not important. ;o)

>> Reading through your description of what it's for, what
>> you actually need is a simple go/no-go test that says
>> "did these two codes arrive too fast?" with the
>> definition of "too fast" being the problem.

> No real problem. I put code to print the current "jiffies"
> count upon SYSRQ make or break. When I press SYSRQ, it
> prints the exact same time for both events.

When you press any of the other keys, does it also print the
exact same time for both events?

> I figured I could just time how long it really takes and
> get an idea of what an appropriate "threshold" value would
> be. Unfortunately it didn't work. The values were indeed
> the same.

Is that just for the SYSRQ key, or for any key?

> I pressed it several times to see if anything changed.
> Sure enough, the odd press generated a jiffie count for
> the break event that was +1 from the make event.

That's to be expected.

> This tells me two things:

> 1) My code is correct for measuring the time.

True.

> 2) The jiffy counter is not fast enough for my needs.

Are you sure?

Remember, all you need is to be able to distinguish between a
keypress that sends both make and break codes together (which is
wrong) and one that sends the codes as the event in question
occurs (which is right).

In your description above, you refer only to what happens when
you press the SYSRQ key, and before you can make this claim, you
need to know whether the same is true of the other keys as well.

As a quick data point, let's look at professional touch typists.
Their typing speed is measured in "words per minute" where a word
is defined as being six key presses. I believe the world record
is around 300 words per minute, but let's be generous and work
out what a typing speed of 450 words per minute would correspond
to. That's about 50% faster than the record.

We have...

   (6 keypresses per word) * (450 words per minute) 2700
   ------------------------------------------------ = ----
             (60 seconds per minute) 60

...which, by my maths, comes out at 45 keys per second, or 90 key
make codes and key break codes combined per second. This is in
agreement with the claim that to convert words per minute to keys
per second, one simply divides the former by 10.

Now, it's a basic rule of physics that to ensure that one samples
an event fast enough to get a true picture of what's happenning,
one needs to sample at least twice as fast as the speed at which
the thing one is measuring is occurring. Therefore, a keyboard
capable of keeping up with this is sampling the key states at
least twice as often as that, and is thus able to send codes out
at 180 codes per second.

You would therefore need a counter that can distinguish between
the arrival times of codes arriving at 180 codes per second to be
able to time every gap.

> So, I need an existing in kernel counter that is a bit
> faster.

Based on the above maths, you would need a counter that measures
time units of 1/200 of a second or shorter to be able to measure
the arrival times for all keys.

> Jiffies are 1/100 of a second on x86 if I'm correct, so
> that would be 10ms per jiffy.

The DEFAULT on an x86 is 1/100 of a second, but I understand that
can be changed by simply changing a single #define in the
sources, I have certainly heard of people running Linux on x86
with it set to use jiffies of 1/1024 second, which is the value
used on the Alpha if my memory's correct.

Personally, I could see good reason for changing that counter to
enable a working fix to be produced where one can't be produced
otherwise, PROVIDING that it doesn't adversely affect the kernel
in other ways.

> The keyboard appears to send the two codes faster than
> that, and I'm guessing not much faster, but a higher
> resolution would be needed to catch things properly.

Based on simple maths, the 1/100 jiffies counter should be able
to distinguish the two cases for typists with speeds of 250 wpm
or below, and for the usual case of speeds below 150 wpm, should
have no problem whatsoever.

> Is there another counter in kernel with higher res? Please
> let me know. I'm going to go snoop around for one right
> now...

I can't answer that question, sorry.

> Here is my current code:

Cut for brevity as I've no comments on it at this time...

>>> I figured if I had the keyboard driver detect the broken
>>> keyboard and only use my special SYSRQ code when a broken
>>> keyboard is there, otherwise make SYSRQ work the same as it
>>> always did, that my patch would have a better chance of
>>> getting in.

>> Have you ever heard of "sticky keys" ? If not, it's a
>> standard accessibility tweak for computers under several
>> operating systems (originally under Windows 2.0 and
>> available under all later versions thereof) that enables
>> disabled people with limited finger control to use a
>> keyboard, and it's also used by people with no hand control
>> at all, including those who have had both hands amputated.

> Yes, I'm familiar with the sticky keys concept, but I have
> no use for it.

Are you sure of that? Remember that just because your broken
keyboard only shows one key with the problem doesn't mean that
there aren't other keyboards that show the same problem for more
than one key, or for other keys - and a solution that solves this
problem for ALL keys is more likely to get in than one that only
solves this problem for one specific key, no matter how important
that key may be.

>> I suspect this is the tweak you refer to, and if so, and
>> you can extend it to provide a full "sticky keys"
>> implementation as standard in the kernel, then I for one
>> would have no problem endorsing it in that disguise. I know
>> several people with suchlike disabilities who would be
>> willing to use Linux were it not for their disability.

> No, thats not what its for. ;o)

You appear to have completely missed the point: Whatever your
patch is for, if it can also be used to solve other problems,
then it WILL be used to solve them. In fact, it would almost
certainly be to your advantage to write it such that it DOES
solve related problems at the same time.

> What it is for is this: My keyboard sends SYSRQ make and
> break simultaneously, thus SYSRQ doesn't work on my machine
> with the existing SYSRQ keyboard code. The existing SYSRQ
> code sets sysrq_enabled when the make code is captured, and
> clears sysrq_enabled when the break code is captured. My
> patch changes this so that the make code enables
> sysrq_enabled, but the break code is completely ignored.
> Instead, the ALT key's break code is used to clear
> sysrq_enabled.

> The idea is that ALT *HAS* to be pressed down anyways in
> order for either SYSRQ make or break to be received, so we
> can use the ALT break code to get out of SYSRQ mode.

There is one problem with that scenario: WHat happens if the user
tries to press ALT-SCRLK and hits the SYSRQ key whilst doing so?
On a correctly working keyboard, the code sequence that would
be presented to the kernel is...

        ALT MAKE
        SYSRQ MAKE
        SYSRQ BREAK
        SCRLK MAKE
        SCRLK BREAK
        ALT BREAK

...and EXACTLY THE SAME sequence would show up on your broken
keyboard, but the sequence that your patch would present to the
kernel is DIFFERENT, namely...

        ALT MAKE
        SYSRQ MAKE
        SCRLK MAKE
        SCRLK BREAK
        ALT BREAK
        SYSRQ BREAK

...and this needs dealing with before your patch works.

One solution would be to define the sequence SYSRQ SCRLK as being
identical to pressing SCRLK on its own, but that's for you to
decide.

> The solution works and works well.

Does that include the above scenario?

> HOWEVER, it changes the way that SYSRQ works from what
> people are used to.

That may not be a bad thing - did you think of that?

> SYSRQ normally works where you press ALT, hold it, press
> SYSRQ, hold it, and then press the final key, then let go
> of everything.

> With my patch, you press ALT, hold it, press SYSRQ, and can
> hold it or let go, and then press the final key. You do not
> need to continue to hold the SYSRQ key down.

> Since this changes the behaviour of the SYSRQ key combo, I
> figured that if I submitted the patch it would be rejected
> because it changes the behaviour that everyone is used to,
> just so that SYSRQ works on a foobar keyboard that maybe 1
> in 500 developers have.

If the solution is specific to just that one key, then yes, it
would almost certainly be rejected. However, a solution that
solved a more generic problem relating to ANY shift key on the
keyboard would have a far better chance of getting in.

> So... I figured if I could have the patch detect if a
> broken keyboard was being used (by timing the time it takes
> in between make and break on SYSRQ), then it could have the
> existing behaviour on normal keyboards, and yet still work
> on my foobar keyboard - but without having to hold down
> SYSRQ because holding it down on my keyboard doesn't matter
> anyways.

Even then, it may get rejected as being code bloat - and you
would almost certainly need to include a new config option after
the "Enable SYSRQ" option such that the following appeared in
"make menuconfig" in the "Kernel hacking" screen...

        [*] Magic SysRq key
        [*] Fix keyboards with broken SysRq behaviour

...as otherwise, you'd almost certainly have the anti-bloat
brigade up in arms at the way you've "bloated the kernel to deal
with a problem they don't have" as they usually claim.

> To do this, I need to time the thing, and it is less than a
> single jiffie for sure. So I need a new counter to use.

As stated previously, you don't actually need to time the event,
but only to detect whether the make/break codes have come too
fast. A similar problem occurs with the automatic decoding of
morse code, and there's a tried and trusted solution in regular
use for which a variation could be used here:

 1. Determine the average rate at which make or break events
    occur, and set TIMEOUT to 2/3 of this value.

 2. Declare any occasion where the interval is less than
    TIMEOUT units as being broken.

Note that this method is not based on the times for the broken
key (which is what you appear to be using), but on the times for
the keys that work fine (which makes much more sense to me).

>>> So, as you can see, this is a SIMPLE problem, and I do not
>>> need RTC, or dedicated PCI hardware timer cards for it. ;o)

>> Very true.

> Well I hope the kernel has a finer res counter that doesn't
> require something like RTC, because otherwise I don't think
> it is feasible - in which case I'll just submit my existing
> working sysrq patch.

If you're insisting on basing your method on the timings of
broken keys, then yes, it will be infeasible to measure the times
by definition: the broken keyboard is sending the codes one after
the other as fast as it can.

Try developing a method based instead on the non-broken keyboard
and you should be able to develop one that can handle typists
with a speed of up to 120 wpm with ease.

Come to think of it, ALT-SYSRQ is neither a standard keypress for
a typist nor one that's easy to press, so you will probably find
that for that specific case, the above method would handle any
typist one threw at the keyboard for that particular combination.

> The other idea I had was to have /proc/sys/kernel/sysrq use
> the existing code if you echo 1 into there to turn it on,
> or to use my code if you echo 2 in there. I asked someone
> for help on how to do this, but didn't get an answer.

Linus has recently expressed his dislike of the use of /proc
files for changing kernel behaviour, so I would tend to suspect
that he would reject any solution incorporating this.

> I have no idea how to use the proc stuff. Would I just
> check the global variable that is set? Or does the code
> that acts upon that clean up the value first?

It's not a global variable in most cases, but one specific to the
particular file you use. It's also not difficult to do.

Best wishes from Riley.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Tue Feb 29 2000 - 21:00:17 EST