Date: Wed, 7 May 2014 16:59:27 +0300 From: Aleksandr Rybalko <ray@freebsd.org> To: Bruce Evans <brde@optusnet.com.au> Cc: "svn-src-head@freebsd.org" <svn-src-head@freebsd.org>, Matthew Fleming <mdf@freebsd.org>, Aleksandr Rybalko <ray@freebsd.org>, "src-committers@freebsd.org" <src-committers@freebsd.org>, "svn-src-all@freebsd.org" <svn-src-all@freebsd.org> Subject: Re: svn commit: r265442 - head/sys/dev/vt Message-ID: <20140507165927.ede049ac7a79b0c19c6d95bf@freebsd.org> In-Reply-To: <20140507001943.F3578@besplex.bde.org> References: <201405061352.s46DqE9a025250@svn.freebsd.org> <CAMBSHm-z_yF5JLfF8U6r=z8xQGrLDVqwnAAjA3k7%2BB2X%2BZ=KSw@mail.gmail.com> <20140507001943.F3578@besplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 7 May 2014 02:26:20 +1000 (EST) Bruce Evans <brde@optusnet.com.au> wrote: > On Tue, 6 May 2014, Matthew Fleming wrote: > > > On Tue, May 6, 2014 at 6:52 AM, Aleksandr Rybalko <ray@freebsd.org> wrote: > >> Log: > >> Implement KDMKTONE ioctl. > > Does it have to have to be even worse than syscons? > > >> Modified: head/sys/dev/vt/vt_core.c > >> ============================================================================== > >> --- head/sys/dev/vt/vt_core.c Tue May 6 13:46:36 2014 (r265441) > >> +++ head/sys/dev/vt/vt_core.c Tue May 6 13:52:13 2014 (r265442) > >> @@ -1732,9 +1732,17 @@ skip_thunk: > >> td->td_frame->tf_rflags &= ~PSL_IOPL; > >> #endif > >> return (0); > >> - case KDMKTONE: /* sound the bell */ > >> - /* TODO */ > >> + case KDMKTONE: { /* sound the bell */ > >> + int freq, period; > > Style bugs: nested declarations, and misindented braces to make the rest > not too ugly without using C++ declarations). Syscons doesn't use any > local variables here. > > >> + > >> + freq = 1193182 / ((*(int*)data) & 0xffff); > > This is a period in nominal x86 i8254 timer cycles, not a frequency. > 1193182 would be a frequency. This is very confusing. The confusion > is reduced a little in kbdcontrol and syscons by spelling the variable > that is spelled 'period' here as 'duration'. > > The current bugs caused by this confusion seem to be: > - the API has been broken. The original API (from SCO?) apparently has > units of x86 timer cycles at the nominal frequency for (*(int*)data). > - inverting the units fixed broken cases but broke working cases. Broken > cases included: > - the default "pitch" of 800 Hz was actually a period of 800 x86 timer > cycles. Its frequency was actually 1193182 / 800 = 1493 Hz. This > affected the default in kbdcontrol and the kernel. > Working cases included anything that conformed to the API: > - kbdcontrol -b 1.800 used to give 800 Hz. Now it gives 800 x86 timer > cycles or 1493 Hz after a double inversion. > The inversion bug is more obvious at frequencies far away from > sqrt(1193182) = 1092 Hz. 800 is only moderately far away. > - variable names are bad. 'pitch' is used for both frequencies and periods. > Variable names were not changed to match inversion of the API, though > sometimes the inversion made the variable name not so bad. > > syscons is better layered here. It passes the undivided "pitch" > ((*(int*)data) & 0xffff) to sc_bell(). sc_bell() implements visual > bell, which I use. Even KDMKTONE gets turned into visual bell. OTOH, > KDMKSOUND makes a "tone", which is actually always a sound. > > Note that the hard-coded frequency 1193182 is almost correct, although > this is x86-specific and even x86 has a variable for the timer > frequency. It is part of the non-broken user API. It is sysbeep()'s > resposibility to convert from nominal x86 cycles to the actual hardware. > This is easier to fix with the magic number not exposed to userland. > Even x86 sysbeep() never bothered to do the conversion. Conversion > on x86 would only give a fix of a few ppm except on exotic hardware. > > > This data comes from a user and can't be trusted. This is a potential > > divide-by-zero. > > This bug has been implemented and executed before. It was in at least > the alpha version. The alpha sysbeep() did an extra inversion, so the > broken cases were reversed relative to the old i386 version, as above. > Better yet, the inversion implemented the divide-by-zero panic, as above. > > I may misremember, but in unquoted parts of the diff I saw a check for > the zero-divisor case. This check is necessary to match the API. 0 > is an out-of-band value that must be translated to a default value. > > > > >> + period = (((*(int*)data)>>16) & 0xffff) * hz / 1000; > > > This is signed shift which I can't recall if it's well-defined if the > > number is negative. Using u_int would definitely be defined. > > Syscons does the same thing here. The behaviour is implementation- > defined IIRC. In practice, negative values for the duration give a > garbage result that is very far from negative. E.g., a duration of > -1 gives 0xffff after shifting. This is independent of whether the > sign bit gets shifted since the high bits are masked off. But the > result is garbage -- masking makes it positive. Then scaling by hz / > 1000 makes 0xffff as large as possible for a duration instead of > negative. Not a problem. > > You can get worse problems from physically impossible frequencies like > 1 Hz and nearly-infinite Hz. Not 0 or infinite Hz since 0 is translated > or 1193182/0 is avoided in non-buggy versions. 1 Hz is physically > impossible and not a problem. Nearly-infinite Hz (a period of 0 or 1 > timer cycles) might damage the speaker, but in practice the speaker > just can't keep up. I think it averages out to not doing anything. > > Bruce Hi Matthew! Hi Bruce! Thank you very much for pointing that. And sorry for my mistakes :) It looks like fixed in r265546. P.S. Bruce, I very like your explanations (all, not only this one), but sometime I got tired before I done with reading. Can you please be a bit less verbose sometime? :) Thanks a lot! WBW -- Aleksandr Rybalko <ray@freebsd.org>
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140507165927.ede049ac7a79b0c19c6d95bf>