Re: svn commit: r354076 - head/sys/dev/ow

2019-10-26 Thread Bruce Evans

On Fri, 25 Oct 2019, Andriy Gapon wrote:


On 25/10/2019 18:46, Ian Lepore wrote:

On Fri, 2019-10-25 at 15:38 +, Andriy Gapon wrote:

Author: avg
Date: Fri Oct 25 15:38:09 2019
New Revision: 354076
URL: https://svnweb.freebsd.org/changeset/base/354076

Log:
  owc_gpiobus_read_data: compare times in sbintime_t units

  Previously the code used sbttous() before microseconds comparison
in one
  place, sbttons() and nanoseconds in another, division by SBT_1US
and
  microseconds in yet another.

  Now the code consistently uses multiplication by SBT_1US to convert
  microseconds to sbintime_t before comparing them with periods
between
  calls to sbinuptime().  This is fast, this is precise enough (below
  0.03%) and the periods defined by the protocol cannot overflow.

  Reviewed by:  imp (D22108)
  MFC after:2 weeks

Modified:
  head/sys/dev/ow/owc_gpiobus.c

Modified: head/sys/dev/ow/owc_gpiobus.c
=
=
--- head/sys/dev/ow/owc_gpiobus.c   Fri Oct 25 15:02:50 2019(r354
075)
+++ head/sys/dev/ow/owc_gpiobus.c   Fri Oct 25 15:38:09 2019(r354
076)
@@ -296,10 +296,10 @@ owc_gpiobus_read_data(device_t dev, struct
ow_timing *
do {
now = sbinuptime();
GETPIN(sc, );
-   } while (sbttous(now - then) < t->t_rdv + 2 && sample == 0);
+   } while (now - then < (t->t_rdv + 2) * SBT_1US && sample == 0);
critical_exit();

-   if (sbttons(now - then) < t->t_rdv * 1000)
+   if (now - then < t->t_rdv * SBT_1US)
*bit = 1;
else
*bit = 0;
@@ -307,7 +307,7 @@ owc_gpiobus_read_data(device_t dev, struct
ow_timing *
/* Wait out the rest of t_slot */
do {
now = sbinuptime();
-   } while ((now - then) / SBT_1US < t->t_slot);
+   } while (now - then < t->t_slot * SBT_1US);

RELBUS(sc);



Unit conversions with sbt times should be done using the macros that
carefully avoid roundoff errors.  I don't understand why you've changed
the code that correctly did use those macros to inline math.


I think that the commit message explains it:
This is fast, this is precise enough (below 0.03%) and the periods defined by
the protocol cannot overflow.

Do you disagree?
Could you please explain in which of the three lines changed the new code is
worse and why?


The old code is worse.  This is partly because the inline functions are
over-engineered and poorly implemented and don't even work.

The first thing improved in the change is:


do {
now = sbinuptime();
GETPIN(sc, );
-   } while (sbttous(now - then) < t->t_rdv + 2 && sample == 0);
+   } while (now - then < (t->t_rdv + 2) * SBT_1US && sample == 0);


sbintime_t is signed so that negative differences work. Scaling negative
differences by SBT_1*S works right.  Scaling of negative difference by the
inline functions attempts to panic, but even the panic is broken (unreachable).

Here 'now' is an uptime and 'then' is presumably a previous uptime, so
now < then "can't happen".  Similar code with non-monotonic or untrusted
times might produce a negative difference.

For efficiency, t_rdv + 2 could be kept as an sbintime.  Scaling it at
runtime gives the cleaner code:

} while (now - then < ustosbt(t->t_rdv + 2) && sample == 0);

Sign extension bugs are further away in this expression.  The arg
(t->t_rdv + 2) is more obviously >= 0 since it is a limit, and all of
the inline functions return a signed type (sbintime_t or int64_t) so
that signed differences work.

The next thing improved is:


-   if (sbttons(now - then) < t->t_rdv * 1000)
+   if (now - then < t->t_rdv * SBT_1US)


This preserves full accuracy and signs for 'now - then' but loses a little
more accuracy than needed for conversion of t_rdv.  But accuracy of t_rdv
is apparently unimportant.  If the last bit in it were important, then it
should be kept as an sbintime and difference like 'now - then' should never
be scaled since even perfect rounding would lose bits.

The final thing improved is:


-   } while ((now - then) / SBT_1US < t->t_slot);
+   } while (now - then < t->t_slot * SBT_1US);


This already used the unscaled 'now - then', but with a style bug (excessive
parentheses.

imp still hasn't replied to my mails that fix some of the bugs in the
overengineerined committed version.  My version is even more overengineered.
I maintain the following version but only use the non-comment parts of
sbttons().  First look at the bugs in the committed sbtons():

XX /*
XX  * Large comment.  The function is not very overengineered except in the
XX  * comment.  Half the detals are wrong.
XX  */
XX static __inline int64_t
XX sbttons(sbintime_t _sbt)
XX {
XX  uint64_t ns;
XX 
XX #ifdef KASSERT

XX  KASSERT(_sbt >= 0, ("Negative values illegal for sbttons: %jx", _sbt));
XX #endif

Multiplication by SBT_1NS used to be 

Re: svn commit: r353640 - head/sys/kern

2019-10-23 Thread Bruce Evans

On Tue, 22 Oct 2019, Alan Somers wrote:


On Wed, Oct 16, 2019 at 7:21 AM Andrew Turner  wrote:


Author: andrew
Date: Wed Oct 16 13:21:01 2019
New Revision: 353640
URL: https://svnweb.freebsd.org/changeset/base/353640

Log:
  Stop leaking information from the kernel through timespec

  The timespec struct holds a seconds value in a time_t and a nanoseconds
  value in a long. On most architectures these are the same size, however
  on 32-bit architectures other than i386 time_t is 8 bytes and long is
  4 bytes.

  Most ABIs will then pad a struct holding an 8 byte and 4 byte value to
  16 bytes with 4 bytes of padding. When copying one of these structs the
  compiler is free to copy the padding if it wishes.


I doubt that most ABIs pad the struct in that case.  Pure 32-bit arches
don't have any 64-bit memory or register operations, so they use 32-bit
longs and don't pessimize structs with 64-bit types in them using padding.

If there are any such ABIs, then there are thousands if not millions more
places to fix.  Every place where a timespec is written must be checked.

E.g., gettimeofday() reduces to microtime().  The implementation of
microtime() happens to fill the timeval fields separately.  That always
leaks kernel context if struct timeval has padding and nothing else
zeros the padding.  And for gettimeofday() it is especially clear that
nothing else zeros the padding.  sys_gettimeofday() allocates a timeval
on the kernel stack; microtime() initializes its fields separately
leaving any padding untouched; copyout() then copies out kernel context.

This commit attempts to fix the different problem that if lower levels
like microtime() were pessimized to initialize the padding, then callers
would have to be careful to preserve this by not using struct
assignments for copying structs.  This is not easy to do.  bcopy() and
copyout() should preserve memory, but there are no guarantees if the
struct is accessed in other ways.  The fix in this commit can easily
not work on arches that have the problem:

bzero(); /* padding now all 0 */
tv.tv_sec = another_tv_sec;
/*
 * Padding now indeterminate (C99 6.2.6.1p6).  It is reasonable
 * for the implementation to use the padding on ABIs that have it,
 * 64-bit stores of registers with uncleared kernel context gives
 * gives the context leak.
 */
tv.tv_nsec = another_tv_nsec;

I don't see anything in C99 that requires padding to remain unchanged
even with no stores in the program.

This problem affects more than time_t's.  It affects all padding.

I next checked the simplest itimer call.  sys_getitimer() doesn't
handle the problem, of course: it allocates a struct itimerval
aitimerval the kernel stack; kern_getitimer() allocates a struct timeval
ctv on the kernel stack; ctv is initialized 1 field at a time in most
cases so its padding remains uninitialized; aitv is inititialized using
a struct assignment in most cases so it has the problem that this
commit attempts to fix.

This is just another bug in 64-bit time_t's, especially on 32-bit arches.
Instead of 32-bit time_t's which work until 2038 or 2106, we have subtle
security holes now.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r353103 - head/sys/net

2019-10-04 Thread Bruce Evans

On Fri, 4 Oct 2019, John Baldwin wrote:


On 10/4/19 6:43 AM, Kyle Evans wrote:

Author: kevans
Date: Fri Oct  4 13:43:07 2019
New Revision: 353103
URL: https://svnweb.freebsd.org/changeset/base/353103

Log:
  tuntap(4): loosen up tunclose restrictions

  Realistically, this cannot work. We don't allow the tun to be opened twice,
  so it must be done via fd passing, fork, dup, some mechanism like these.
  Applications demonstrably do not enforce strict ordering when they're
  handing off tun devices, so the parent closing before the child will easily
  leave the tun/tap device in a bad state where it can't be destroyed and a
  confused user because they did nothing wrong.

  Concede that we can't leave the tun/tap device in this kind of state because
  of software not playing the TUNSIFPID game, but it is still good to find and
  fix this kind of thing to keep ifconfig(8) up-to-date and help ensure good
  discipline in tun handling.


Why are you using d_close for last close anyway?  It's not really reliable 
compared
to using cdevpriv and a cdevpriv dtor.


Correct last-close close is necessarily very complicated.  Here is the
ttydev_close() part of mine for the tty driver.  It uses cdevpriv to a
fault.

One fault from this is that since tracking closes actually works, it
breaks mmap() since cdevpriv is associated with open files, but mmap()
is supposed to work on closed files and even for open files cdevpriv
is not available in vm_fault().  So my fixes make vm_fault() on ttys
always fail, since tty_mmap() always fails on entry since cdevpriv is
invalid.

XX Index: tty.c
XX ===
XX --- tty.c(revision 332488)
XX +++ tty.c(working copy)

I only have this patch for an old version of FreeBSD.

XX @@ -368,37 +693,157 @@
XX  struct thread *td __unused)
XX  {
XX  struct tty *tp = dev->si_drv1;
XX +int *ocountp;
XX +int error;
XX 
XX  	tty_lock(tp);

XX +tty_trace(T_C_START, "start", dev, fflag, NO_E);
XX +if (tp->t_dev == NULL) {
XX +tty_trace(T_C_DONE | 0x2000 | T_V, "done (no t_dev)", dev,
XX +fflag, ENXIO);
XX +tty_unlock(tp);
XX +return (ENXIO);
XX +}
XX +tp->t_acount++;
XX +ocountp = ttydev_ocountp(dev);
XX +if (*ocountp <= 0) {
XX +tty_trace(0x4000 | T_C_DONE, "done (already closed)", dev,
XX +fflag, 0);
XX +if (fflag & FREVOKE) {
XX +(*ttydev_devgenp(dev))++;
XX +tty_wakeupall(tp);
XX +}
XX +ttydev_exit(tp);
XX +return (0);
XX +}
XX +if ((fflag & FREVOKE) == 0) {
XX +if (tty_devgen() != tty_filegen()) {

This is the main use of cdevpriv.  A file generation is stored in cdevpriv
and returned by tty_filegen() (return -1 if cdevpriv is invalid).  A device
generation is one of 4 generation counts stored in the tty struct and is
returned by tty_devgen().  When these are not equal, it means a revoke in
the past or an even more complicated condition.

XX +tty_trace(T_C_DONE | 0x8000 | T_I,
XX +"done (revoked before starting)", dev, fflag, 0);
XX +ttydev_exit(tp);
XX +return (0);
XX +}
XX +if (*ocountp > 1) {
XX +(*ocountp)--;
XX +tty_trace(0x1 | T_C_DONE, "done (non-last)",
XX +dev, fflag, 0);
XX +ttydev_exit(tp);
XX +return (0);
XX +}
XX +if (!tty_gone(tp)) {
XX +tty_trace(0x2, "tty_drain", dev, fflag, NO_E);
XX +/*
XX + * This used to be broken by forcibly clearing
XX + * TF_STOPPED earlier, and even asserted that.
XX + * Expect more "correct" hangs now.  The special
XX + * timeout amelioriates this.  Only software flow
XX + * control was cleared anyway.
XX + */
XX +error = tty_drain(tp, 1);
XX +tty_trace(0x4, "tty_drain done", dev, fflag, error);
XX +/*
XX + * Do exactly the same as before draining.
XX + * Revoking must be checked for explicitly,
XX + * since tty_drain() returns ENXIO if both
XX + * revoked and gone, and ERESTART can mean
XX + * EINTR.
XX + *
XX + * Ignore errors in draining, since they are
XX + * nonstandard except for EINTR and even EINTR
XX + * is too hard for callers to handle.
XX + */
XX +if (tty_devgen() != tty_filegen()) {
XX +tty_trace(0x8 | T_C_DONE | T_I,
XX +   

Re: svn commit: r352795 - head/lib/libc/sys

2019-10-02 Thread Bruce Evans

On Tue, 1 Oct 2019, Ed Maste wrote:


On Tue, 1 Oct 2019 at 12:23, Brooks Davis  wrote:


This isn't true with CHERI and as a result I've moved the variadic
argument handling (except for syscall() and __syscall()) into libc.


My grep found: open, openat, fcntl, semsys, msgsys, shmsys
Is that the full list?


I already wrote that this is quite broken for open and fcntl in POSIX.
hecking some details shows that it is more fundamentally broken than I
thought:
- for open(), the type of the mode argument passed by the caller is
  unspecified.  Whatever it is, it is "taken" as type mode_t, whatevr
  "taking" is.  Since historical mode_t has only 16 bits, it can be
  represented by int even on systems with 16-bit ints, so the caller
  can start with either mode_t or int provided mode_t is no larger than
  historical mode_t and ints are either larger than 16 bits or 16 bits
  and not too exotic (the sign bit might cause problems if not 2's
  complement)
- for fcntl() with F_SETOWN, the type of the pid argument passed by the
  caller is unspecified.  Whatever it is, it is "taken" as type int.
  Thus if pid_t is larger than int, passing all possible values of
  pid_t is impossible.  If also PID_MAX <= INT_MAX and all values of
  pid_t are actually <= PID_MAX, then all possible (positive) values
  can be passed, but the iplementation may have to do extra work to
  properly break a passed __default_promotion_of(pid_t) type by "taking"
  it as an int.

  This was discussed on the POSIX list recently.  IMO it is too late and
  not useful to change the old specification to "take" the arg as anything
  except int.  So pid_t might as well be specified as being a signed integer
  type whose default promotion is int.  It is currently specified as being
  a signed integer type (with any size or exoticness).

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r352846 - head/lib/libc/sys

2019-09-29 Thread Bruce Evans

On Sun, 29 Sep 2019, Konstantin Belousov wrote:


On Sat, Sep 28, 2019 at 05:15:48PM +, Warner Losh wrote:

Author: imp
Date: Sat Sep 28 17:15:48 2019
New Revision: 352846
URL: https://svnweb.freebsd.org/changeset/base/352846

Log:
  Revert the mode_t -> int changes and add a warning in the BUGS section 
instead.

  While FreeBSD's implementation of these expect an int inside of libc, that's 
an
  implementation detail that we can hide from the user as it's the natural
  promotion of the current mode_t type and before it is used in the kernel, it's
  converted back to the narrower type that's the current definition of mode_t. 
As
  such, documenting int is at best confusing and at worst misleading. Instead 
add
  a note that these args are variadic and as such calling conventions may differ
  from non-variadic arguments.

Modified:
  head/lib/libc/sys/mq_open.2
  head/lib/libc/sys/open.2

Modified: head/lib/libc/sys/mq_open.2
==
--- head/lib/libc/sys/mq_open.2 Sat Sep 28 14:20:28 2019(r352845)
+++ head/lib/libc/sys/mq_open.2 Sat Sep 28 17:15:48 2019(r352846)
@@ -37,7 +37,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd September 15, 2014
+.Dd September 28, 2019
 .Dt MQ_OPEN 2
 .Os
 .Sh NAME
@@ -133,7 +133,7 @@ Create a message queue.
 It requires two additional arguments:
 .Fa mode ,
 which is of type
-.Vt int ,
+.Vt mode_t ,
 and
 .Fa attr ,
 which is a pointer to an
@@ -317,6 +317,13 @@ This implementation places strict requirements on the
 it must begin with a slash
 .Pq Ql /
 and contain no other slash characters.
+.Pp
+The
+.Fa mode
+and
+.Fa attr
+arguments are variadic and may result in different calling conventions
+than might otherwise be expected.
 .Sh COPYRIGHT
 Portions of this text are reprinted and reproduced in electronic form
 from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --

Modified: head/lib/libc/sys/open.2
==
--- head/lib/libc/sys/open.2Sat Sep 28 14:20:28 2019(r352845)
+++ head/lib/libc/sys/open.2Sat Sep 28 17:15:48 2019(r352846)
@@ -28,7 +28,7 @@
 .\" @(#)open.28.2 (Berkeley) 11/16/93
 .\" $FreeBSD$
 .\"
-.Dd September 17, 2019
+.Dd September 28, 2019
 .Dt OPEN 2
 .Os
 .Sh NAME
@@ -61,7 +61,7 @@ In this case
 and
 .Fn openat
 require an additional argument
-.Fa "int mode" ,
+.Fa "mode_t mode" ,
 and the file is created with mode
 .Fa mode
 as described in
@@ -615,3 +615,8 @@ permits searches.
 The present implementation of the
 .Fa openat
 checks the current permissions of directory instead.
+.Pp
+The
+.Fa mode
+argument is variadic and may result in different calling conventions
+than might otherwise be expected.

This note is also very confusing.

Assume that somebody knows calling conventions and then see this note.
Now she would be equally misdirected because it is completely not clear
what different conventions are mentioned there, esp. because there are no.

Also, as I noted before, this note in whatever form does not belongs to
BUSS section.


I was going to say "Indeed.  The man page already gives the type mode_t
for the mode, so the fix should be to remind the reader that since open()
is variadic, the caller MUST supply an arg whose type is the default
promotion of mode_t [and this is most easily done by starting with or
casting to an arg whose type is precisely mode_t].

POSIX gets this wronger.  It says "the file mode shall be set to the
value of the argument following the oflag argument taken as type
mode_t".  It never defines the actual type of this arg.  Since open()
is variadic, the actual type is the default promotion of whatever the
caller passes.  Nothing forbids the caller passing a long long or even
a long double, or even any type with any encoding.  Literally, this
requires the implementation to "take" the arg as a mode_t using an
unspecified conversion method after using magic beyond va_arg() to
determine the type and value of the arg.  POSIX give an example where
the arg type is precisely mode_t, but this is just an example of one
arg type that works.  All this was in the 2001 version of POSIX and
remains unfixed in the 2018 version.

So the man page was wrong after all.  It was not bug for bug compatible
with POSIX, since it says that the additional argument is "mode_t mode"
but POSIX allows any type that can be "taken" as a mode_t.

This shouldn't change the fix.  The BUGS section is not the place to
document bugs in POSIX.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r352795 - head/lib/libc/sys

2019-09-27 Thread Bruce Evans

On Fri, 27 Sep 2019, Konstantin Belousov wrote:


On Fri, Sep 27, 2019 at 08:32:20PM +0200, Mateusz Guzik wrote:

On 9/27/19, Warner Losh  wrote:

Author: imp
Date: Fri Sep 27 16:11:47 2019
New Revision: 352795
URL: https://svnweb.freebsd.org/changeset/base/352795

Log:
  Document varadic args as int, since you can't have short varadic args
(they are
  promoted to ints).

  - `mode_t` is `uint16_t` (`sys/sys/_types.h`)
  - `openat` takes variadic args
  - variadic args cannot be 16-bit, and indeed the code uses int
  - the manpage currently kinda implies the argument is 16-bit by saying
`mode_t`

  Prompted by Rust things: https://github.com/tailhook/openat/issues/21
  Submitted by: Greg V at unrelenting
  Differential Revision: https://reviews.freebsd.org/D21816

Modified:
  head/lib/libc/sys/mq_open.2
  head/lib/libc/sys/open.2

Modified: head/lib/libc/sys/mq_open.2
==
--- head/lib/libc/sys/mq_open.2 Fri Sep 27 15:28:30 2019(r352794)
+++ head/lib/libc/sys/mq_open.2 Fri Sep 27 16:11:47 2019(r352795)
@@ -133,7 +133,7 @@ Create a message queue.
 It requires two additional arguments:
 .Fa mode ,
 which is of type
-.Vt mode_t ,
+.Vt int ,
 and
 .Fa attr ,
 which is a pointer to an

Modified: head/lib/libc/sys/open.2
==
--- head/lib/libc/sys/open.2Fri Sep 27 15:28:30 2019(r352794)
+++ head/lib/libc/sys/open.2Fri Sep 27 16:11:47 2019(r352795)
@@ -61,7 +61,7 @@ In this case
 and
 .Fn openat
 require an additional argument
-.Fa "mode_t mode" ,
+.Fa "int mode" ,
 and the file is created with mode
 .Fa mode
 as described in


But opengroup says it is mode_t. Perhaps it is mode_t which needs
to be changed?


POSIX needed to be changed before it became standard in 1988, but it is
too late now.  Types shorter than int shouldn't be used in APIs since
they cause ABI and API problems.  Especially in 1988 when non-prototyped
functions were common.  Non-prototyped functions use the default promotions
much like variadic functions.  open() is variadic, so its mode_t arg is
always promoted, but 'int chmod(const char *path, mode_t mode)' is just
wrong since in 1988 prototypes were not required and the prototype
matching the K API was 'int chmod(const char *path,
__default_promotion_of(mode_t) mode)'.


Yes, users must pass mode_t, and the man page is written for users.
Implementation needs to be aware of the implicit promotion and handle
it accordingly.

In theory, mode_t might be wider than int.


Indeed.  mode_t can also be the same size as int, but unsigned.  This
happens naturally if int is 16 bits, which POSIX allowed before 2001.
In V7, mode_t was really a 16-bit u_int, but it was type-punned to int.

When mode_t is u_int or wider than int, then the promotion is null, and
variadic and K do it consistently (but the arg type before the call
must be precisely mode_t, not int).

The POSIX list recently discussed a related problem with variadic pid_t
args for fcntl().  For F_SETOWN, the original arg type should be pid_t
as for mode_t for open().  Howver, F_GETOWN only returns int, so pids
larger than INT_MAX cannot work and making pid_t different from int is
just foot shooting.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r351700 - head/lib/libc/string

2019-09-25 Thread Bruce Evans

On Wed, 25 Sep 2019, Ed Maste wrote:


On Fri, 20 Sep 2019 at 08:14, Bruce Evans  wrote:


Optimizing this function [memchr] is especially unimportant,


Why?


Because it is almost never used, and most of its uses are unimportant.

It is used a whole 26 times in all of /usr/src/*bin:
- sh/exec.c:   1 especially^N unimportant use after execve() fails
- dmesg/dmesg.c:   2 uses; speed unimportant in utilitities like dmesg
 that parse small data
- sort/sort.c: 2 uses for reading lines; speed possibly important
- sed/process.c:   2 uses in options parsing; speed unimportant
- grep/file.c: 3 uses for reading lines; speed possibly important,
   but if you want speed in utility that parses large
   data then you should use a special lexer and not
   general functions even to find newlines
- gcore/elfcore.c: 1 use; speed unimportant
- diff/diffreg.c:  1 use for detecting binaries; speed probably unimportant
- mkimg/mkimg.c:   2 uses for writes; speed unimportant since i/o-bound
- truss/syscalls.c:1 use; speed unimportant
- indent/pr_comment.c: 1 use; speed unimportant
- ppp/*.c: 4 uses; speed unimportant
- timed/readmsg.c: 1 use; speed unimportant
- inetd/inetd.c:   1 use; speed unimportant
- jail/config.c:   1 use; speed unimportant
- daemon/daemon.c: 1 use; speed unimportant
- bhyve/gdb.c: 2 uses; speed unimportant


Really, we should provide optimized assembly implementations of string
functions deemed important, but it will take time for that to happen
on all architectures.


Really, we should provide optimized (usually non-assembly) implementations
of no more than copying memory, and not deem any other string function as
important (since none are).  Even optimizing copying memory gives speed
improvements of less than 1% in most programs.  Assembly implementations
are usually pessimal, and become more so with time.  E.g., if you write
memcpy() as something like *dst++ = *src++, then if the size is known at
compile time, then clang will optimize to use AVXn in some cases.  Handling
the same number of cases in assembly is impractical.  My experiments to
optimize copying memory only handle about 30 cases, but I only tried to
optimized for large copies and stopped adding cases 15 years ago when it
became clear that too many cases would be needed.

clang knows that it doesn't understand memory, so it doesn't do
optimizations like this if the size is not known at compile time.  It
calls the library, which in FreeBSD doesn't even know that it doesn't
understand memory.




and this version has mounds of style bugs.


Yes, I've wondered about applying style(9) to the handful of imported
string routines. In general we don't really expect ongoing updates, so
it's probably no concern from a maintenance perspective.


- do {
- if (*p++ == (unsigned char)c)
- return ((void *)(p - 1));
- } while (--n != 0);


Old KNF code.  In the !__GNUC__ #else clause , this is replaced by
equivalent code with a style that is very far from KNF.


Functionally equivalent, although I compared the compiled output of
both cases and what's currently there is somewhat smaller. Note that
it's not an #else case, the equivalent loop is used in both cases -
handling the non-word-size residue in the __GNUC__ case.


+void *memchr(const void *src, int c, size_t n)
+{
+ const unsigned char *s = src;
+ c = (unsigned char)c;
+#ifdef __GNUC__
+ for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--);
+ if (n && *s != c) {
+ typedef size_t __attribute__((__may_alias__)) word;


This seems to have no dependencies on __GNUC__ except the use of anti-aliasing,


Yes, that is the reason.


I checked that this optimization actually works.  For long strings, it is
almost sizeof(size_t) times faster, by accessing memory with a size
sizeof(size_t).  size_t is a not very good way of hard-coding the word size.


Indeed - I wouldn't have imported this change if I didn't observe a
reasonable benefit when trying it out. As for word size it could be
replaced using LONG_BIT I suppose (as strspn.c, strlen.c), if it's
getting reworked anyway.


But how do you know that long strings are most common?  For short strings,
it is better to have low overhead.

LONG_BIT is another bad way of encoding the word size.  On arches with
correctly sized longs, long is twice as wide as either a machine register
or the maximum memory access width.  So it is usually twice the word size
if correct.  register_t is closer to being correct.


Related silly optimizations:
- i386 has memchr() in asm.  This uses scasb, which was last optimal on the
   8088, or perhaps the original i386.  On freefall, it is several times slower
   than the naive translation of the naive C code.


I posted a review (https:

Re: svn commit: r352661 - head/sys/netinet/tcp_stacks

2019-09-24 Thread Bruce Evans

On Tue, 24 Sep 2019, Randall Stewart wrote:


Log:
 lets put (void) in a couple of functions to keep older platforms that
 are stuck with gcc happy (ppc). The changes are needed in both bbr and
 rack.


You mean "Don't use K declarations.  clang is too broken to warn about
K declarations even when requested to do so using -Wstrict-prototypes,
but some archss (e.g., ppc) haven't been downgraded to use clang yet,
so K declarations in kernel code are still detected in FreeBSD eventually.

WERROR was recently broken for gcc-4.2 by making warnings not fatal, so
the changes are not strictly needed.  I use gcc-4.2 on x86 for all except
about 10 files with ifuncs, and the broken WERROR causes serious problems:
gcc-4.2 doesn't support ifuncs, so I have to downgrade to clang to compile
files with ifuncs.  ifuncs only generate warnings and this used to be fatal,
so files ifuncs were easy to find.  Now, garbage object files are created
and the errors are obscure linkage errors.

Of course, I fix this by restoring WERROR=-Werror.  This clearly shows the
bitrot that tcp_lro.c doesn't compile.  It has casts of pointers uint64_t
instead of to uintptr_t.  On i386, these types have different sizes, so
gcc detects the type mismatch.  clang is too broken to report this type
mismatch.  The upcast happens to be safe on x86 but gcc's warning is good
for portability (source portability to compilers that detect the type
mismatch in some way, and binary portabiily to future arches with pointers
larger than uint64_t).

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r351700 - head/lib/libc/string

2019-09-20 Thread Bruce Evans

On Mon, 2 Sep 2019, Ed Maste wrote:


Author: emaste
Date: Mon Sep  2 13:56:44 2019
New Revision: 351700
URL: https://svnweb.freebsd.org/changeset/base/351700

Log:
 libc: Use musl's optimized memchr

 Parentheses added to HASZERO macro to avoid a GCC warning.

 Reviewed by:   kib, mjg
 Obtained from: musl (snapshot at commit 4d0a82170a)
 Sponsored by:  The FreeBSD Foundation
 Differential Revision: https://reviews.freebsd.org/D17631

Modified:
 head/lib/libc/string/memchr.c

Modified: head/lib/libc/string/memchr.c
==
--- head/lib/libc/string/memchr.c   Mon Sep  2 13:55:31 2019
(r351699)
+++ head/lib/libc/string/memchr.c   Mon Sep  2 13:56:44 2019
(r351700)
@@ -1,55 +1,54 @@
/*-
- * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-License-Identifier: MIT
 *
- * Copyright (c) 1990, 1993
- * The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2005-2014 Rich Felker, et al.
 *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.


I prefer Torek's version.  Optimizing this function is especially unimportant,
and this version has mounds of style bugs.


-void *
-memchr(const void *s, int c, size_t n)
-{
-   if (n != 0) {
-   const unsigned char *p = s;
+#define SS (sizeof(size_t))
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) (((x)-ONES) & ~(x) & HIGHS)

-   do {
-   if (*p++ == (unsigned char)c)
-   return ((void *)(p - 1));
-   } while (--n != 0);


Old KNF code.  In the !__GNUC__ #else clausew , this is replaced by
equivalent code with a style that is very far from KNF.

If compilers understood this function, then they could reasonably optimize
the old code in very AMD ways, e.g., use AVX512.  This is not so reasonable
for the new code.  clang does such optimizations to a fault, but knows that
it doesn't understand this code or even strlen(), so it does a naive
translation.


+void *memchr(const void *src, int c, size_t n)
+{
+   const unsigned char *s = src;
+   c = (unsigned char)c;
+#ifdef __GNUC__
+   for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--);
+   if (n && *s != c) {
+   typedef size_t __attribute__((__may_alias__)) word;


This seems to have no dependencies on __GNUC__ except the use of anti-aliasing,
and that dependendency is broken (very old versions of gcc don't even have
__attribute__(()), and old versions don't have __may_alias).


+   const word *w;
+   size_t k = ONES * c;
+   for (w = (const void *)s; n>=SS && !HASZERO(*w^k); w++, n-=SS);
+   s = (const void *)w;
}


This is cryptic as well as non-KNF.  libc/string/strlen.c uses the same
dubious optimization method, but it is at least clearly written and it is
even in KNF.


-   return (NULL);
+#endif
+   for (; n && *s != c; s++, n--);
+   return n ? (void *)s : 0;
}


I checked that this optimization actually works.  For long strings, it is
almost sizeof(size_t) times faster, by accessing memory with a size
sizeof(size_t).  size_t is a not very good way of hard-coding the word size.

Related silly optimizations:
- i386 has memchr() in asm.  This uses scasb, which was last optimal on the
  8088, or perhaps the original i386.  On freefall, it is several times slower
  than the naive translation of the naive C code.
- i386 pessimizes several old string functions using scasb.  amd64 mostly
  doesn't copy this mistake.  Similarly for wide char string functions.
  Optimizing these is even more unimportant and just writing them in asm is
  quite complicated.  They are perhaps not fully pessimized in asm on i386.
  amd64 doesn't have any of them in asm.
- i386 also does dubious alignment optimizations
- amd64 pessimizes strcpy() by implementing it as a C wrapper for stpcpy().
  The wrapper code is MI, but is only used for amd64.
- amd64 stpcpy(), strcat() and strcmp() uses the fancy optimization using
  the 0x0101... and 0x8080...  tricks (as in this version of memchr()
  except not so cryptically since the constants are literal instead
  of constructed using macros from the word type).  Optimizing strcat()
  some of these functions is unimportant.  Worth doing at most once,
  in the C version.
- the generic strlen() (but no other generic string function) is optimized
  using the 0x0101... and 0x8080... tricks.  This optimization is dubious
  since it is a pessimization for short strings.  Compilers often inline
  string functions, especially strlen() anyway.  I think x86 compilers
  used to routinely inline strlen(), but now they know that they don't
  understand it, so they just call the library strlen() for most strings
  that are not known at compile time.  This results in the fancy optimization
  

Re: svn commit: r351659 - in head: contrib/libc++/include contrib/netbsd-tests/lib/libc/ssp gnu/lib/libssp include lib/libc/stdio

2019-09-13 Thread Bruce Evans

On Sun, 1 Sep 2019, Cy Schubert wrote:

I'm replying to this reply since I lost the original mail.


In message <201909011612.x81gc5dw097...@repo.freebsd.org>, Ed Maste writes:

Author: emaste
Date: Sun Sep  1 16:12:05 2019
New Revision: 351659
URL: https://svnweb.freebsd.org/changeset/base/351659

Log:
  libc: remove gets

  gets is unsafe and shouldn't be used (for many years now).  Leave it in
  the existing symbol version so anything that previously linked aginst it
  still runs, but do not allow new software to link against it.

  (The compatability/legacy implementation must not be static so that
  the symbol and in particular the compat sym gets@FBSD_1.0 make it
  into libc.)

  PR:   222796 (exp-run)
  Reported by:  Paul Vixie
  Reviewed by:  allanjude, cy, eadler, gnn, jhb, kib, ngie (some earlie
r)
  Relnotes: Yes
  Sponsored by: The FreeBSD Foundation
  Differential Revision:https://reviews.freebsd.org/D12298


This breaks  for most old standards, and bogotitifies the ifdefs
that attempt to support old standards.   used to be more careful
with these ifdefs than most system headers.

C11 removed gets(), but POSIX.1-2017 (Issue 7) still has it (marked as
obsolescent).  Thus this change breaks support for all versions of POSIX.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346641 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Wed Apr 24 16:03:35 2019
New Revision: 346641
URL: https://svnweb.freebsd.org/changeset/base/346641

Log:
  Avoid hiding and unhiding the mouse cursor when copying bitmaps to the
  screen.  Instead, copy a merged bitmap 1 line at a time.
  
  This fixes flashing of the cursor and is faster in all modes (especially
  in planar modes).

Modified:
  head/lib/libvgl/bitmap.c
  head/lib/libvgl/mouse.c
  head/lib/libvgl/vgl.h

Modified: head/lib/libvgl/bitmap.c
==
--- head/lib/libvgl/bitmap.cWed Apr 24 15:54:18 2019(r346640)
+++ head/lib/libvgl/bitmap.cWed Apr 24 16:03:35 2019(r346641)
@@ -167,8 +167,17 @@ int
 __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
  VGLBitmap *dst, int dstx, int dsty, int width, int hight)
 {
-  int srcline, dstline, yend, yextra, ystep;
-
+  byte *buffer, *p;
+  int mousemerge, srcline, dstline, yend, yextra, ystep;
+  
+  mousemerge = 0;
+  if (hight < 0) {
+hight = -hight;
+mousemerge = (dst == VGLDisplay &&
+ VGLMouseOverlap(dstx, dsty, width, hight));
+if (mousemerge)
+  buffer = alloca(width*src->PixelBytes);
+  }
   if (srcx>src->VXsize || srcy>src->VYsize
|| dstx>dst->VXsize || dsty>dst->VYsize)
 return -1;  
@@ -204,8 +213,13 @@ __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
   }
   for (srcline = srcy + yextra, dstline = dsty + yextra; srcline != yend;
srcline += ystep, dstline += ystep) {
-WriteVerticalLine(dst, dstx, dstline, width, 
-  src->Bitmap+(srcline*src->VXsize+srcx)*dst->PixelBytes);
+p = src->Bitmap+(srcline*src->VXsize+srcx)*dst->PixelBytes;
+if (mousemerge && VGLMouseOverlap(dstx, dstline, width, 1)) {
+  bcopy(p, buffer, width*src->PixelBytes);
+  p = buffer;
+  VGLMouseMerge(dstx, dstline, width, p);
+}
+WriteVerticalLine(dst, dstx, dstline, width, p);
   }
   return 0;
 }
@@ -214,36 +228,29 @@ int
 VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
  VGLBitmap *dst, int dstx, int dsty, int width, int hight)
 {
-  int error, mouseoverlap;
+  int error;
 
+  if (hight < 0)
+return -1;
   if (src == VGLDisplay)
 src = 
   if (src->Type != MEMBUF)
 return -1; /* invalid */
   if (dst == VGLDisplay) {
 VGLMouseFreeze();
-mouseoverlap = VGLMouseOverlap(dstx, dsty, width, hight);
-if (mouseoverlap)
-  VGLMousePointerHide();
+__VGLBitmapCopy(src, srcx, srcy, , dstx, dsty, width, hight);
 error = __VGLBitmapCopy(src, srcx, srcy, , dstx, dsty,
 width, hight);
-if (error != 0) {
-  if (mouseoverlap)
-VGLMousePointerShow();
-  VGLMouseUnFreeze();
+if (error != 0)
   return error;
-}
 src = 
 srcx = dstx;
 srcy = dsty;
   } else if (dst->Type != MEMBUF)
 return -1; /* invalid */
-  error = __VGLBitmapCopy(src, srcx, srcy, dst, dstx, dsty, width, hight);
-  if (dst == VGLDisplay) {
-if (mouseoverlap)
-  VGLMousePointerShow();
+  error = __VGLBitmapCopy(src, srcx, srcy, dst, dstx, dsty, width, -hight);
+  if (dst == VGLDisplay)
 VGLMouseUnFreeze();
-  }
   return error;
 }
 

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Wed Apr 24 15:54:18 2019(r346640)
+++ head/lib/libvgl/mouse.c Wed Apr 24 16:03:35 2019(r346641)
@@ -356,6 +356,25 @@ VGLMouseOverlap(int x, int y, int width, int hight)
 }
 
 void
+VGLMouseMerge(int x, int y, int width, byte *line)
+{
+  int pos, x1, xend, xstart;
+
+  xstart = x;
+  if (xstart < VGLMouseXpos)
+xstart = VGLMouseXpos;
+  xend = x + width;
+  if (xend > VGLMouseXpos + MOUSE_IMG_SIZE)
+xend = VGLMouseXpos + MOUSE_IMG_SIZE;
+  for (x1 = xstart; x1 < xend; x1++) {
+pos = (y - VGLMouseYpos) * MOUSE_IMG_SIZE + x1 - VGLMouseXpos;
+if (VGLMouseAndMask->Bitmap[pos])
+  bcopy(>Bitmap[pos * VGLDisplay->PixelBytes],
+[(x1 - x) * VGLDisplay->PixelBytes], VGLDisplay->PixelBytes);
+  }
+}
+
+void
 VGLMouseUnFreeze()
 {
   INTON();

Modified: head/lib/libvgl/vgl.h
==
--- head/lib/libvgl/vgl.h   Wed Apr 24 15:54:18 2019(r346640)
+++ head/lib/libvgl/vgl.h   Wed Apr 24 16:03:35 2019(r346641)
@@ -136,6 +136,7 @@ void VGLMouseRestore(void);
 int VGLMouseStatus(int *x, int *y, char *buttons);
 void VGLMouseFreeze(void);
 int VGLMouseFreezeXY(int x, int y);
+void VGLMouseMerge(int x, int y, int width, byte *line);
 int VGLMouseOverlap(int x, int y, int width, int hight);
 void VGLMouseUnFreeze(void);
 /* simple.c */


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346416 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Fri Apr 19 20:29:49 2019
New Revision: 346416
URL: https://svnweb.freebsd.org/changeset/base/346416

Log:
  Fix copying of overlapping bitmaps.  The cases of copying within the
  screen bitmap and within a single MEMBUF were broken when first source
  line is before the first destination line and the sub-bitmaps overlap.
  
  The fix just copies horizontal lines in reverse order when the first
  source line is before the first destination line.  This switches
  directions unnecessarily in some cases, but the switch is about as
  fast as doing a precise detection of overlaps.  When the first lines
  are the same, there can be undetected overlap in the horizontal
  direction.  The old code already handles this mostly accidentally by
  using bcopy() for MEMBUFs and by copying through a temporary buffer
  for the screen bitmap although the latter is sub-optimal in direct
  modes.

Modified:
  head/lib/libvgl/bitmap.c

Modified: head/lib/libvgl/bitmap.c
==
--- head/lib/libvgl/bitmap.cFri Apr 19 20:23:39 2019(r346415)
+++ head/lib/libvgl/bitmap.cFri Apr 19 20:29:49 2019(r346416)
@@ -269,7 +269,7 @@ int
 __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
  VGLBitmap *dst, int dstx, int dsty, int width, int hight)
 {
-  int srcline, dstline;
+  int srcline, dstline, yend, yextra, ystep;
 
   if (srcx>src->VXsize || srcy>src->VYsize
|| dstx>dst->VXsize || dsty>dst->VYsize)
@@ -296,8 +296,17 @@ __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
  hight=dst->VYsize-dsty;
   if (width < 0 || hight < 0)
  return -1;
+  yend = srcy + hight;
+  yextra = 0;
+  ystep = 1;
+  if (src->Bitmap == dst->Bitmap && srcy < dsty) {
+yend = srcy;
+yextra = hight - 1;
+ystep = -1;
+  }
   if (src->Type == MEMBUF) {
-for (srcline=srcy, dstline=dsty; srclineBitmap+(srcline*src->VXsize+srcx)*dst->PixelBytes);
 }
@@ -319,7 +328,8 @@ __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
 } else {
   p = buffer;
 }
-for (srcline=srcy, dstline=dsty; srclinehttps://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346631 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Wed Apr 24 13:15:56 2019
New Revision: 346631
URL: https://svnweb.freebsd.org/changeset/base/346631

Log:
  Fix some races and screeen clearing in VGLEnd().
  
  The mouse signal SIGUSR2 was not turned off for normal termination and
  in some other cases.  Thus mouse signals arriving after the frame
  buffer was unmapped always caused fatal traps.  The fatal traps occurred
  about 1 time in 5 if the mouse was wiggled while vgl is ending.
  
  The screen switch signal SIGUSR1 was turned off after clearing the
  flag that it sets.  Unlike the mouse signal, this signal is handled
  synchronously, but VGLEnd() does screen clearing which does the
  synchronous handling.  This race is harder to lose.  I think it can
  get vgl into deadlocked state (waiting in the screen switch handler
  with SIGUSR1 to leave that state already turned off).
  
  Turn off the mouse cursor before clearing the screen in VGLEnd().
  Otherwise, clearing is careful to not clear the mouse cursor.  Undrawing
  an active mouse cursor uses a lot of state, so is dangerous for abnormal
  termination, but so is clearing.  Clearing is slow and is usually not
  needed, since the kernel also does it (not quite right).

Modified:
  head/lib/libvgl/main.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Wed Apr 24 09:05:45 2019(r346630)
+++ head/lib/libvgl/main.c  Wed Apr 24 13:15:56 2019(r346631)
@@ -73,11 +73,11 @@ struct vt_mode smode;
 
   if (!VGLInitDone)
 return;
-  VGLInitDone = 0;
+  signal(SIGUSR1, SIG_IGN);
+  signal(SIGUSR2, SIG_IGN);
   VGLSwitchPending = 0;
   VGLAbortPending = 0;
-
-  signal(SIGUSR1, SIG_IGN);
+  VGLMousePointerHide();
 
   if (VGLMem != MAP_FAILED) {
 VGLClear(VGLDisplay, 0);


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346580 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Mon Apr 22 19:31:16 2019
New Revision: 346580
URL: https://svnweb.freebsd.org/changeset/base/346580

Log:
  Fix mouse cursor coloring in depths > 8 (previously, a hack that only
  worked right for white interiors and black borders was used).  Advertise
  this by changing the default colors to a red interior and a white
  border (the same as the kernel default).  Add undocumented env variables
  for changing these colors.  Also change to the larger and better-shaped
  16x10 cursor sometimes used in the kernel.  The kernel choice is
  fancier, but libvgl is closer to supporting the larger cursors needed
  in newer modes.
  
  The (n)and-or logic for the cursor doesn't work right for more than 2
  colors.  The (n)and part only masks out all color bits for the pixel
  under the cursor when all bits are set in the And mask.  With more
  complicated logic, the non-masked bits could be used to implement
  translucent cursors, but they actually just gave strange colors
  (especially in packed and planar modes where the bits are indirect
  through 1 or 2 palettes so it is hard to predict the final color).
  They also gave a bug for writing pixels under the cursor.  The
  non-masked bits under the cursor were not combined in this case.
  
  Drop support for combining with bits under the cursor by making any nonzero
  value in the And mask mean all bits set.
  
  Convert the Or mask (which is represented as a half-initialized 256-color
  bitmap) to a fully initialized bitmap with the correct number of colors.
  The 256-color representation must be as in 3:3:2 direct mode iff the final
  bitmap has more than 256 colors.  The conversion of colors is not very
  efficient, so convert at initialization time.

Modified:
  head/lib/libvgl/bitmap.c
  head/lib/libvgl/mouse.c
  head/lib/libvgl/simple.c
  head/lib/libvgl/vgl.h

Modified: head/lib/libvgl/bitmap.c
==
--- head/lib/libvgl/bitmap.cMon Apr 22 19:24:21 2019(r346579)
+++ head/lib/libvgl/bitmap.cMon Apr 22 19:31:16 2019(r346580)
@@ -274,3 +274,27 @@ VGLBitmapAllocateBits(VGLBitmap *object)
 return -1;
   return 0;
 }
+
+void
+VGLBitmapCvt(VGLBitmap *src, VGLBitmap *dst)
+{
+  u_long color;
+  int dstpos, i, pb, size, srcpb, srcpos;
+
+  size = src->VXsize * src->VYsize;
+  srcpb = src->PixelBytes;
+  if (srcpb <= 0)
+srcpb = 1;
+  pb = dst->PixelBytes;
+  if (pb == srcpb) {
+bcopy(src->Bitmap, dst->Bitmap, size * pb);
+return;
+  }
+  if (srcpb != 1)
+return;/* not supported */
+  for (srcpos = dstpos = 0; srcpos < size; srcpos++) {
+color = VGLrgb332ToNative(src->Bitmap[srcpos]);
+for (i = 0; i < pb; i++, color >>= 8)
+dst->Bitmap[dstpos++] = color;
+  }
+}

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Mon Apr 22 19:24:21 2019(r346579)
+++ head/lib/libvgl/mouse.c Mon Apr 22 19:31:16 2019(r346580)
@@ -39,7 +39,11 @@ __FBSDID("$FreeBSD$");
 #include 
 #include "vgl.h"
 
-#define X 0xff
+#define BORDER 0xff/* default border -- light white in rgb 3:3:2 */
+#define INTERIOR 0xa0  /* default interior -- red in rgb 3:3:2 */
+#define X  0xff/* any nonzero in And mask means part of cursor */
+#define B  BORDER
+#define I  INTERIOR
 static byte StdAndMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -49,34 +53,36 @@ static byte StdAndMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] 
X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,
X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
+   X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,
+   X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,
X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
-   0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,0,
-   0,0,0,X,X,X,X,X,0,0,0,0,0,0,0,0,
-   0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,
-   0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+   X,X,X,0,X,X,X,X,0,0,0,0,0,0,0,0,
+   X,X,0,0,X,X,X,X,0,0,0,0,0,0,0,0,
+   0,0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,
+   0,0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,
+   0,0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,
 };
 static byte StdOrMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
-   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   0,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   0,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   0,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
-   0,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
-   0,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,
-   0,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
-   0,X,X,0,X,0,0,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   

svn commit: r346639 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Wed Apr 24 15:35:29 2019
New Revision: 346639
URL: https://svnweb.freebsd.org/changeset/base/346639

Log:
  Refactor mouse freezing and fix some minor bugs.
  
  VGLMouseFreeze() now only defers mouse signals and leaves it to higher
  levels to hide and unhide the mouse cursor if necessary.  (It is never
  necessary, but is done to simplify the implementation.  It is slow and
  flashes the cursor.  It is still done for copying bitmaps and clearing.)
  
  VGLMouseUnFreeze() now only undoes 1 level of freezing.  Its old
  optimization to reduce mouse redrawing is too hard to do with unhiding
  in higher levels, and its undoing of multiple levels was a historical
  mistake.
  
  VGLMouseOverlap() determines if a region overlaps the (full) mouse region.
  
  VGLMouseFreezeXY() is the freezing and a precise overlap check combined
  for the special case of writing a single pixel.  This is the single-pixel
  case of the old VGLMouseFreeze() with cleanups.
  
  Fixes:
  - check in more cases that the application didn't pass an invalid VIDBUF
  - check for errors from copying a bitmap to the shadow buffer
  - freeze the mouse before writing to the shadow buffer in all cases.  This
was not done for the case of writing a single pixel (there was a race)
  - don't spell the #defined values for VGLMouseShown as 0, 1 or boolean.

Modified:
  head/lib/libvgl/bitmap.c
  head/lib/libvgl/mouse.c
  head/lib/libvgl/simple.c
  head/lib/libvgl/vgl.h

Modified: head/lib/libvgl/bitmap.c
==
--- head/lib/libvgl/bitmap.cWed Apr 24 15:02:59 2019(r346638)
+++ head/lib/libvgl/bitmap.cWed Apr 24 15:35:29 2019(r346639)
@@ -214,23 +214,36 @@ int
 VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
  VGLBitmap *dst, int dstx, int dsty, int width, int hight)
 {
-  int error;
+  int error, mouseoverlap;
 
   if (src == VGLDisplay)
 src = 
   if (src->Type != MEMBUF)
 return -1; /* invalid */
   if (dst == VGLDisplay) {
-VGLMouseFreeze(dstx, dsty, width, hight, 0);
-__VGLBitmapCopy(src, srcx, srcy, , dstx, dsty, width, hight);
+VGLMouseFreeze();
+mouseoverlap = VGLMouseOverlap(dstx, dsty, width, hight);
+if (mouseoverlap)
+  VGLMousePointerHide();
+error = __VGLBitmapCopy(src, srcx, srcy, , dstx, dsty,
+width, hight);
+if (error != 0) {
+  if (mouseoverlap)
+VGLMousePointerShow();
+  VGLMouseUnFreeze();
+  return error;
+}
 src = 
 srcx = dstx;
 srcy = dsty;
   } else if (dst->Type != MEMBUF)
 return -1; /* invalid */
   error = __VGLBitmapCopy(src, srcx, srcy, dst, dstx, dsty, width, hight);
-  if (dst == VGLDisplay)
+  if (dst == VGLDisplay) {
+if (mouseoverlap)
+  VGLMousePointerShow();
 VGLMouseUnFreeze();
+  }
   return error;
 }
 

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Wed Apr 24 15:02:59 2019(r346638)
+++ head/lib/libvgl/mouse.c Wed Apr 24 15:35:29 2019(r346639)
@@ -89,7 +89,7 @@ static VGLBitmap VGLMouseStdOrMask = 
 VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdOrMask);
 static VGLBitmap *VGLMouseAndMask, *VGLMouseOrMask;
 static int VGLMouseVisible = 0;
-static int VGLMouseShown = 0;
+static int VGLMouseShown = VGL_MOUSEHIDE;
 static int VGLMouseXpos = 0;
 static int VGLMouseYpos = 0;
 static int VGLMouseButtons = 0;
@@ -316,48 +316,47 @@ VGLMouseStatus(int *x, int *y, char *buttons)
   return VGLMouseShown;
 }
 
-int
-VGLMouseFreeze(int x, int y, int width, int hight, u_long color)
+void
+VGLMouseFreeze(void)
 {
-INTOFF();
-if (width > 1 || hight > 1 || (color & 0xc000) == 0) { /* bitmap */
-  if (VGLMouseShown == 1) {
-int overlap;
+  INTOFF();
+}
 
-if (x > VGLMouseXpos)
-  overlap = (VGLMouseXpos + MOUSE_IMG_SIZE) - x;
-else
-  overlap = (x + width) - VGLMouseXpos;
-if (overlap > 0) {
-  if (y > VGLMouseYpos)
-overlap = (VGLMouseYpos + MOUSE_IMG_SIZE) - y;
-  else
-overlap = (y + hight) - VGLMouseYpos;
-  if (overlap > 0)
-VGLMousePointerHide();
-} 
-  }
-}
-else { /* bit */
-  if (VGLMouseShown &&
-  x >= VGLMouseXpos && x < VGLMouseXpos + MOUSE_IMG_SIZE &&
-  y >= VGLMouseYpos && y < VGLMouseYpos + MOUSE_IMG_SIZE) {
-if (color & 0x8000) {  /* Set */
-  if (VGLMouseAndMask->Bitmap 
-[(y-VGLMouseYpos)*MOUSE_IMG_SIZE+(x-VGLMouseXpos)]) {
-return 1;
-  }   
-}   
-  }   
-}
+int
+VGLMouseFreezeXY(int x, int y)
+{
+  INTOFF();
+  if (VGLMouseShown != VGL_MOUSESHOW)
+return 0;
+  if (x >= VGLMouseXpos && x < VGLMouseXpos + MOUSE_IMG_SIZE &&
+  y >= 

svn commit: r346488 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Sun Apr 21 16:17:35 2019
New Revision: 346488
URL: https://svnweb.freebsd.org/changeset/base/346488

Log:
  Use a shadow buffer and never read from the frame buffer.  Remove large slow
  code for reading from the frame buffer.
  
  Reading from the frame buffer is usually much slower than writing to
  the frame buffer.  Typically 10 to 100 times slower.  It old modes,
  it takes many more PIOs, and in newer modes with no PIOs writes are
  often write-combined while reads remain uncached.
  
  Reading from the frame buffer is not very common, so this change doesn't
  give speedups of 10 to 100 times.  My main test case is a floodfill()
  function that reads about as many pixels as it writes.  The speedups
  are typically a factor of 2 to 4.
  
  Duplicating writes to the shadow buffer is slower when no reads from the
  frame buffer are done, but reads are often done for the pixels under the
  mouse cursor, and doing these reads from the shadow buffer more than
  compensates for the overhead of writing the shadow buffer in at least the
  slower modes.  Management of the mouse cursor also becomes simpler.
  
  The shadow buffer doesn't take any extra memory, except twice as much
  in old 4-plane modes.  A buffer for holding a copy of the frame buffer
  was allocated up front for use in the screen switching signal handler.
  This wasn't changed when the handler was made async-signal safe.  Use
  the same buffer the shadow (but make it twice as large in the 4-plane
  modes), and remove large special code for writing it as well as large
  special code for reading ut.  It used to have a rawer format in the
  4-plane modes.  Now it has a bitmap format which takes twice as much
  memory but can be written almost as fast without special code.
  
  VIDBUFs that are not the whole frame buffer were never supported, and the
  change depends on this.  Check for invalid VIDBUFs in some places and do
  nothing.  The removed code did something not so good.

Modified:
  head/lib/libvgl/bitmap.c
  head/lib/libvgl/main.c
  head/lib/libvgl/mouse.c
  head/lib/libvgl/simple.c
  head/lib/libvgl/vgl.h

Modified: head/lib/libvgl/bitmap.c
==
--- head/lib/libvgl/bitmap.cSun Apr 21 14:45:18 2019(r346487)
+++ head/lib/libvgl/bitmap.cSun Apr 21 16:17:35 2019(r346488)
@@ -163,108 +163,6 @@ WriteVerticalLine(VGLBitmap *dst, int x, int y, int wi
   }
 }
 
-static void
-ReadVerticalLine(VGLBitmap *src, int x, int y, int width, byte *line)
-{
-  int i, bit, pos, count, planepos, start_offset, end_offset, offset;
-  int width2, len;
-  byte *address;
-  byte *VGLPlane[4];
-
-  switch (src->Type) {
-  case VIDBUF4S:
-start_offset = (x & 0x07);
-end_offset = (x + width) & 0x07;
-count = (width + start_offset) / 8;
-if (end_offset)
-  count++;
-VGLPlane[0] = VGLBuf;
-VGLPlane[1] = VGLPlane[0] + count;
-VGLPlane[2] = VGLPlane[1] + count;
-VGLPlane[3] = VGLPlane[2] + count;
-for (i=0; i<4; i++) {
-  outb(0x3ce, 0x04);
-  outb(0x3cf, i);
-  pos = VGLAdpInfo.va_line_width*y + x/8;
-  for (width2 = count; width2 > 0; ) {
-   offset = VGLSetSegment(pos);
-   len = min(VGLAdpInfo.va_window_size - offset, width2);
-   bcopy(src->Bitmap + offset, [i][count - width2], len);
-   pos += len;
-   width2 -= len;
-  }
-}
-goto read_planar;
-  case VIDBUF4:
-address = src->Bitmap + VGLAdpInfo.va_line_width * y + x/8;
-start_offset = (x & 0x07);
-end_offset = (x + width) & 0x07;
-count = (width + start_offset) / 8;
-if (end_offset)
-  count++;
-VGLPlane[0] = VGLBuf;
-VGLPlane[1] = VGLPlane[0] + count;
-VGLPlane[2] = VGLPlane[1] + count;
-VGLPlane[3] = VGLPlane[2] + count;
-for (i=0; i<4; i++) {
-  outb(0x3ce, 0x04);
-  outb(0x3cf, i);
-  bcopy(address, [i][0], count);
-}
-read_planar:
-pos = 0;
-planepos = 0;
-bit = 7 - start_offset;
-while (pos < width) {
-  for (; bit >= 0 && pos < width; bit--, pos++) {
-line[pos] = (VGLPlane[0][planepos] & (1VXsize * y + x) * src->PixelBytes;
-while (width > 0) {
-  offset = VGLSetSegment(pos);
-  i = min(VGLAdpInfo.va_window_size - offset, width);
-  bcopy(src->Bitmap + offset, line, i);
-  line += i;
-  pos += i;
-  width -= i;
-}
-break;
-  case MEMBUF:
-  case VIDBUF8:
-  case VIDBUF16:
-  case VIDBUF24:
-  case VIDBUF32:
-address = src->Bitmap + (src->VXsize * y + x) * src->PixelBytes;
-bcopy(address, line, width * src->PixelBytes);
-break;
-  default:
-;
-  }
-}
-
 int
 __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
  VGLBitmap *dst, int dstx, int dsty, int width, int 

svn commit: r346280 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Tue Apr 16 15:52:04 2019
New Revision: 346280
URL: https://svnweb.freebsd.org/changeset/base/346280

Log:
  Sigh, r346279 was also a test version with the reduced size doubled (so
  it was actually double the full size in current kernels where the reduction
  is null, so overran the mmapped() buffer).

Modified:
  head/lib/libvgl/main.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Tue Apr 16 15:41:45 2019(r346279)
+++ head/lib/libvgl/main.c  Tue Apr 16 15:52:04 2019(r346280)
@@ -275,7 +275,7 @@ VGLInit(int mode)
* get the same efficiency and bugs for all kernels.
*/
   if (VGLModeInfo.vi_mode >= M_VESA_BASE)
-VGLBufSize = 2*VGLAdpInfo.va_line_width*VGLModeInfo.vi_height*
+VGLBufSize = VGLAdpInfo.va_line_width*VGLModeInfo.vi_height*
  VGLModeInfo.vi_planes;
   VGLBuf = malloc(VGLBufSize);
   if (VGLBuf == NULL) {


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346486 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Sun Apr 21 10:33:09 2019
New Revision: 346486
URL: https://svnweb.freebsd.org/changeset/base/346486

Log:
  Fix missing restoring of the mouse cursor position, the border color and the
  blank state after a screen switch.

Modified:
  head/lib/libvgl/main.c
  head/lib/libvgl/mouse.c
  head/lib/libvgl/simple.c
  head/lib/libvgl/vgl.h

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Sun Apr 21 09:13:56 2019(r346485)
+++ head/lib/libvgl/main.c  Sun Apr 21 10:33:09 2019(r346486)
@@ -436,6 +436,9 @@ VGLCheckSwitch()
   VGLDisplay->Xsize = VGLModeInfo.vi_width;
   VGLDisplay->Ysize = VGLModeInfo.vi_height;
   VGLSetVScreenSize(VGLDisplay, VGLDisplay->VXsize, VGLDisplay->VYsize);
+  VGLRestoreBlank();
+  VGLRestoreBorder();
+  VGLMouseRestore();
   VGLPanScreen(VGLDisplay, VGLDisplay->Xorigin, VGLDisplay->Yorigin);
   switch (VGLDisplay->Type) {
   case VIDBUF4S:

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Sun Apr 21 09:13:56 2019(r346485)
+++ head/lib/libvgl/mouse.c Sun Apr 21 10:33:09 2019(r346486)
@@ -272,6 +272,22 @@ VGLMouseInit(int mode)
   return 0;
 }
 
+void
+VGLMouseRestore(void)
+{
+  struct mouse_info mouseinfo;
+
+  INTOFF();
+  mouseinfo.operation = MOUSE_GETINFO;
+  if (ioctl(0, CONS_MOUSECTL, ) == 0) {
+mouseinfo.operation = MOUSE_MOVEABS;
+mouseinfo.u.data.x = VGLMouseXpos;
+mouseinfo.u.data.y = VGLMouseYpos;
+ioctl(0, CONS_MOUSECTL, );
+  }
+  INTON();
+}
+
 int
 VGLMouseStatus(int *x, int *y, char *buttons)
 {

Modified: head/lib/libvgl/simple.c
==
--- head/lib/libvgl/simple.cSun Apr 21 09:13:56 2019(r346485)
+++ head/lib/libvgl/simple.cSun Apr 21 10:33:09 2019(r346486)
@@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$");
 #include 
 #include "vgl.h"
 
+static int VGLBlank;
+static byte VGLBorderColor;
 static byte VGLSavePaletteRed[256];
 static byte VGLSavePaletteGreen[256];
 static byte VGLSavePaletteBlue[256];
@@ -637,6 +639,12 @@ VGLSetPaletteIndex(byte color, byte red, byte green, b
 }
 
 void
+VGLRestoreBorder(void)
+{
+  VGLSetBorder(VGLBorderColor);
+}
+
+void
 VGLSetBorder(byte color)
 {
   if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT && ioctl(0, KDENABIO, 0))
@@ -646,11 +654,18 @@ VGLSetBorder(byte color)
   outb(0x3C0,0x11); outb(0x3C0, color); 
   inb(0x3DA);
   outb(0x3C0, 0x20);
+  VGLBorderColor = color;
   if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
 ioctl(0, KDDISABIO, 0);
 }
 
 void
+VGLRestoreBlank(void)
+{
+  VGLBlankDisplay(VGLBlank);
+}
+
+void
 VGLBlankDisplay(int blank)
 {
   byte val;
@@ -660,6 +675,7 @@ VGLBlankDisplay(int blank)
   VGLCheckSwitch();
   outb(0x3C4, 0x01); val = inb(0x3C5); outb(0x3C4, 0x01);
   outb(0x3C5, ((blank) ? (val |= 0x20) : (val &= 0xDF)));
+  VGLBlank = blank;
   if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
 ioctl(0, KDDISABIO, 0);
 }

Modified: head/lib/libvgl/vgl.h
==
--- head/lib/libvgl/vgl.h   Sun Apr 21 09:13:56 2019(r346485)
+++ head/lib/libvgl/vgl.h   Sun Apr 21 10:33:09 2019(r346486)
@@ -130,6 +130,7 @@ void VGLMouseAction(int dummy);
 void VGLMouseSetImage(VGLBitmap *AndMask, VGLBitmap *OrMask);
 void VGLMouseSetStdImage(void);
 int VGLMouseInit(int mode);
+void VGLMouseRestore(void);
 int VGLMouseStatus(int *x, int *y, char *buttons);
 int VGLMouseFreeze(int x, int y, int width, int hight, u_long color);
 void VGLMouseUnFreeze(void);
@@ -142,6 +143,8 @@ void VGLFilledBox(VGLBitmap *object, int x1, int y1, i
 void VGLEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color);
 void VGLFilledEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long 
color);
 void VGLClear(VGLBitmap *object, u_long color);
+void VGLRestoreBlank(void);
+void VGLRestoreBorder(void);
 void VGLRestorePalette(void);
 void VGLSavePalette(void);
 void VGLSetPalette(byte *red, byte *green, byte *blue);


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346279 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Tue Apr 16 15:41:45 2019
New Revision: 346279
URL: https://svnweb.freebsd.org/changeset/base/346279

Log:
  Oops, r346278 committed a test version with the change annulled.

Modified:
  head/lib/libvgl/main.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Tue Apr 16 15:31:23 2019(r346278)
+++ head/lib/libvgl/main.c  Tue Apr 16 15:41:45 2019(r346279)
@@ -274,7 +274,7 @@ VGLInit(int mode)
* be too slow, and malloc() may fail).  Restrict ourselves similarly to
* get the same efficiency and bugs for all kernels.
*/
-  if (0 && VGLModeInfo.vi_mode >= M_VESA_BASE)
+  if (VGLModeInfo.vi_mode >= M_VESA_BASE)
 VGLBufSize = 2*VGLAdpInfo.va_line_width*VGLModeInfo.vi_height*
  VGLModeInfo.vi_planes;
   VGLBuf = malloc(VGLBufSize);


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346454 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Sat Apr 20 20:29:03 2019
New Revision: 346454
URL: https://svnweb.freebsd.org/changeset/base/346454

Log:
  Make libvgl mostly work without superuser privilege in direct modes by
  not doing any unnecessary PIO instructions or refusing to start when the
  i/o privilege needed for these instructions cannot be acquired.
  
  This turns off useless palette management in direct modes.  Palette
  management had no useful effect since the hardware palette is not used
  in these modes.
  
  This transiently acquires i/o privilege if possible as needed to give
  VGLSetBorder() and VGLBlankDisplay() a chance of working.  Neither has
  much chance of working.  I was going to drop support for them in direct
  modes, but found that VGLBlankDisplay() still works with an old graphics
  card on a not so old LCD monitor.
  
  This has some good side effects: reduce glitches for managing the palette
  for screen switches, and speed up and reduce async-signal-unsafeness in
  mouse cursor drawing.

Modified:
  head/lib/libvgl/main.c
  head/lib/libvgl/mouse.c
  head/lib/libvgl/simple.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Sat Apr 20 17:16:36 2019(r346453)
+++ head/lib/libvgl/main.c  Sat Apr 20 20:29:03 2019(r346454)
@@ -93,7 +93,8 @@ struct vt_mode smode;
 size[2] = VGLOldVInfo.font_size;;
 ioctl(0, KDRASTER, size);
   }
-  ioctl(0, KDDISABIO, 0);
+  if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT)
+ioctl(0, KDDISABIO, 0);
   ioctl(0, KDSETMODE, KD_TEXT);
   smode.mode = VT_AUTO;
   ioctl(0, VT_SETMODE, );
@@ -176,7 +177,7 @@ VGLInit(int mode)
   if (VGLDisplay == NULL)
 return -2;
 
-  if (ioctl(0, KDENABIO, 0)) {
+  if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT && ioctl(0, KDENABIO, 0)) {
 free(VGLDisplay);
 return -3;
   }
@@ -370,7 +371,8 @@ VGLCheckSwitch()
 
 VGLSwitchPending = 0;
 if (VGLOnDisplay) {
-  ioctl(0, KDENABIO, 0);
+  if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT)
+ioctl(0, KDENABIO, 0);
   ioctl(0, KDSETMODE, KD_GRAPHICS);
   ioctl(0, VGLMode, 0);
   VGLCurWindow = 0;
@@ -531,7 +533,8 @@ VGLCheckSwitch()
   munmap(VGLDisplay->Bitmap, VGLAdpInfo.va_window_size);
   ioctl(0, VGLOldMode, 0);
   ioctl(0, KDSETMODE, KD_TEXT);
-  ioctl(0, KDDISABIO, 0);
+  if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT)
+ioctl(0, KDDISABIO, 0);
   ioctl(0, VT_RELDISP, VT_TRUE);
   VGLDisplay->Bitmap = VGLBuf;
   VGLDisplay->Type = MEMBUF;

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Sat Apr 20 17:16:36 2019(r346453)
+++ head/lib/libvgl/mouse.c Sat Apr 20 20:29:03 2019(r346454)
@@ -111,10 +111,12 @@ VGLMousePointerShow()
   if (!VGLMouseVisible) {
 INTOFF();
 VGLMouseVisible = 1;
-crtcidx = inb(0x3c4);
-crtcval = inb(0x3c5);
-gdcidx = inb(0x3ce);
-gdcval = inb(0x3cf);
+if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) {
+  crtcidx = inb(0x3c4);
+  crtcval = inb(0x3c5);
+  gdcidx = inb(0x3ce);
+  gdcval = inb(0x3cf);
+}
 __VGLBitmapCopy(VGLDisplay, VGLMouseXpos, VGLMouseYpos, 
  , 0, 0, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
 bcopy(VGLMouseSave.Bitmap, buffer.Bitmap,
@@ -128,10 +130,12 @@ VGLMousePointerShow()
   }
 __VGLBitmapCopy(, 0, 0, VGLDisplay, 
  VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
-outb(0x3c4, crtcidx);
-outb(0x3c5, crtcval);
-outb(0x3ce, gdcidx);
-outb(0x3cf, gdcval);
+if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) {
+  outb(0x3c4, crtcidx);
+  outb(0x3c5, crtcval);
+  outb(0x3ce, gdcidx);
+  outb(0x3cf, gdcval);
+}
 INTON();
   }
 }
@@ -144,16 +148,20 @@ VGLMousePointerHide()
   if (VGLMouseVisible) {
 INTOFF();
 VGLMouseVisible = 0;
-crtcidx = inb(0x3c4);
-crtcval = inb(0x3c5);
-gdcidx = inb(0x3ce);
-gdcval = inb(0x3cf);
+if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) {
+  crtcidx = inb(0x3c4);
+  crtcval = inb(0x3c5);
+  gdcidx = inb(0x3ce);
+  gdcval = inb(0x3cf);
+}
 __VGLBitmapCopy(, 0, 0, VGLDisplay, 
  VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
-outb(0x3c4, crtcidx);
-outb(0x3c5, crtcval);
-outb(0x3ce, gdcidx);
-outb(0x3cf, gdcval);
+if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) {
+  outb(0x3c4, crtcidx);
+  outb(0x3c5, crtcval);
+  outb(0x3ce, gdcidx);
+  outb(0x3cf, gdcval);
+}
 INTON();
   }
 }

Modified: head/lib/libvgl/simple.c
==
--- head/lib/libvgl/simple.cSat Apr 20 17:16:36 2019(r346453)
+++ head/lib/libvgl/simple.cSat Apr 20 20:29:03 2019

Re: svn commit: r346554 - head/sys/netinet

2019-09-03 Thread Bruce Evans

On Mon, 22 Apr 2019, Bjoern A. Zeeb wrote:


On 22 Apr 2019, at 14:20, Bjoern A. Zeeb wrote:

Log:
  Remove some excessive brackets.

  No functional change.


But it includes a stye bug; sorry; I had re-indented the lines to validate 
the change.  Ill remedy this with the follow-up commit which will split 
that block up anyway.


Also, it removes excessive parentheses, not excessive brackets.

I think excessive brackets are just syntax errors.  E.g., a[[i]].

Excessive braces are not syntax errors, but I've never more than single
excessive ones.  E.g.,

if (foo != 0) {
bar();
}

is a common style bug, but

if (foo != 0) {{
bar();
  }}

s unusual.

Bruce


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346278 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Tue Apr 16 15:31:23 2019
New Revision: 346278
URL: https://svnweb.freebsd.org/changeset/base/346278

Log:
  Quick fix for slow clearing and context switches of large frame buffers
  with old kernels, by breaking the support for large frame buffers in the
  same way as for current kernels.
  
  Large frame buffers may be too large to map into kva, and the kernel
  (syscons) only uses the first screen page anyway, so r203535, r205557
  and 248799 limit the buffer size in VESA modes to the first screen
  page, apparently without noticing that this breaks applications by
  using the same limit for user mappings as for kernel mappings.  In
  vgl, this makes the virtual screen the same as the physical screen.
  
  However, this is almost a feature since clearing and switching large
  (usually mostly unused) frame buffers takes too long.  E.g., on a 16
  year old low-end AGP card it takes about 12 seconds to clear the 128MB
  frame buffer in old kernels that map it all and also map it with slow
  attributes (e.g., uncacheable).  Older PCI cards are even slower, but
  usually have less memory.  Newer PCIe cards are faster, but may have
  many GB of memory.  Also, vgl malloc()s a shadow buffer with the same
  size as the frame buffer, so large frame buffers are even more wasteful
  in applications than in the kernel.
  
  Use the same limit in vgl as in newer kernels.
  
  Virtual screens and panning still work in non-VESA modes that have
  more than 1 page.  The reduced buffer size in the kernel also breaks
  mmap() of the last physical page in modes where the reduced size is
  not a multiple of the physical page size.  The same reduction in vgl
  only reduces the virtual screen size.

Modified:
  head/lib/libvgl/main.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Tue Apr 16 14:29:12 2019(r346277)
+++ head/lib/libvgl/main.c  Tue Apr 16 15:31:23 2019(r346278)
@@ -264,6 +264,19 @@ VGLInit(int mode)
   else
 VGLBufSize = max(VGLAdpInfo.va_line_width*VGLModeInfo.vi_height,
 VGLAdpInfo.va_window_size)*VGLModeInfo.vi_planes;
+  /*
+   * The above is for old -CURRENT.  Current -CURRENT since r203535 and/or
+   * r248799 restricts va_buffer_size to the displayed size in VESA modes to
+   * avoid wasting kva for mapping unused parts of the frame buffer.  But all
+   * parts were usable here.  Applying the same restriction to user mappings
+   * makes our virtualization useless and breaks our panning, but large frame
+   * buffers are also difficult for us to manage (clearing and switching may
+   * be too slow, and malloc() may fail).  Restrict ourselves similarly to
+   * get the same efficiency and bugs for all kernels.
+   */
+  if (0 && VGLModeInfo.vi_mode >= M_VESA_BASE)
+VGLBufSize = 2*VGLAdpInfo.va_line_width*VGLModeInfo.vi_height*
+ VGLModeInfo.vi_planes;
   VGLBuf = malloc(VGLBufSize);
   if (VGLBuf == NULL) {
 VGLEnd();


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346276 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Tue Apr 16 14:28:33 2019
New Revision: 346276
URL: https://svnweb.freebsd.org/changeset/base/346276

Log:
  Fix a variable name in r346215.  Clearing of the right of the screen was
  broken, except it worked accidentally in most cases where the virtual
  screen is larger than the physical screen.

Modified:
  head/lib/libvgl/simple.c

Modified: head/lib/libvgl/simple.c
==
--- head/lib/libvgl/simple.cTue Apr 16 14:07:14 2019(r346275)
+++ head/lib/libvgl/simple.cTue Apr 16 14:28:33 2019(r346276)
@@ -515,7 +515,7 @@ VGLClear(VGLBitmap *object, u_long color)
 for (i = 0; i < object->VXsize; i++)
   bcopy(, src.Bitmap + i * object->PixelBytes, object->PixelBytes);
 for (i = 0; i < object->VYsize; i++)
-  __VGLBitmapCopy(, 0, 0, object, 0, i, object->VYsize, 1);
+  __VGLBitmapCopy(, 0, 0, object, 0, i, object->VXsize, 1);
 break;
 
   case VIDBUF8X:


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346215 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Sun Apr 14 13:37:50 2019
New Revision: 346215
URL: https://svnweb.freebsd.org/changeset/base/346215

Log:
  For writing and reading single pixels, avoid some pessimizations for
  depths > 8.  Add some smaller optimizations for these depths.  Use a
  more generic method for all depths >= 8, although this gives tiny
  pessimizations for these depths.
  
  For clearing the whole frame buffer, avoid the same pessimizations
  for depths > 8.  Add some larger optimizations for these depths.  Use
  an even more generic method for all depths >= 8 to give the optimizations
  for depths > 8 and a tiny pessimization for depth 8.
  
  The main pessimization was that old versions of bcopy() copy 1 byte at a
  time for all trailing bytes.  (i386 still does this.  amd64 now pessimizzes
  large sizes instead of small ones if the CPU supports ERMS.  dev/fb gets
  this wrong by mostly not using the bcopy() family or the technically correct
  bus space functions but by mostly copying 2 bytes at a time using an
  unoptimized loop without even volatile declarations to prevent the compiler
  rewriting it.)
  
  The sizes here are 1, 2, 3 or 4 bytes, so depths 9-16 were up to twice as
  slow as necessary and depths 17-24 were up to 3 times slower than necessary.
  Fix this (except depths 17-24 are still up to 2 times slower than necessary)
  by using (builtin) memcpy() instead of bcopy() and reorganizing so that the
  complier can see the small constant sizes.  Reduce special cases while
  reorganizing although this is slightly slower than adding special cases.
  The compiler inlining (and even -O2 vs -O0) makes little difference compared
  with reducing the number of accesses except on modern hardware it gives a
  small improvement.
  
  Clearing was also pessimized mainly by the extra accesses.  Fix it quite
  differently by creating a MEMBUF containing 1 line (in fast memory using
  a slow method) and copying this.  This is only slightly slower than reducing
  everything to efficient memset()s and bcopy()s, but simpler, especially
  for the segmented case.  This works for planar modes too, but don't use it
  then since the old method was actually optimal for planar modes (it works
  by moving the slow i/o instructions out of inner loops), while for direct
  modes the slow instructions were all in the invisible inner loop in bcopy().
  
  Use htole32() and le32toh() and some type puns instead of unoptimized
  functions for converting colors.  This optimization is mostly in the noise.
  libvgl is only supported on x86, so it could hard-code the assumption that
  the byte order is le32, but the old conversion functions didn't hard-code
  this.

Modified:
  head/lib/libvgl/simple.c

Modified: head/lib/libvgl/simple.c
==
--- head/lib/libvgl/simple.cSun Apr 14 13:17:40 2019(r346214)
+++ head/lib/libvgl/simple.cSun Apr 14 13:37:50 2019(r346215)
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
 
 #include 
 #include 
+#include 
 #include "vgl.h"
 
 static byte VGLSavePaletteRed[256];
@@ -44,96 +45,44 @@ static byte VGLSavePaletteBlue[256];
 #define min(x, y)  (((x) < (y)) ? (x) : (y))
 #define max(x, y)  (((x) > (y)) ? (x) : (y))
 
-static void
-color2mem(u_long color, byte *b, int len)
-{
-  switch (len) {
-  case 4:
-b[3] = (color >> 24) & 0xff;
-/* fallthrough */
-  case 3:
-b[2] = (color >> 16) & 0xff;
-/* fallthrough */
-  case 2:
-b[1] = (color >> 8) & 0xff;
-/* fallthrough */
-  case 1:
-  default:
-b[0] = color & 0xff;
-break;
-  }
-
-  return;
-}
-
-static u_long
-mem2color(byte *b, int len)
-{
-  u_long color = 0;
-
-  switch (len) {
-  case 4:
-color |= (b[3] & 0xff) << 24;
-/* fallthrough */
-  case 3:
-color |= (b[2] & 0xff) << 16;
-/* fallthrough */
-  case 2:
-color |= (b[1] & 0xff) << 8;
-/* fallthrough */
-  case 1:
-  default:
-color |= (b[0] & 0xff);
-break;
-  }
-
-  return color;
-}
-
 void
 VGLSetXY(VGLBitmap *object, int x, int y, u_long color)
 {
   int offset;
-  byte b[4];
 
   VGLCheckSwitch();
   if (x>=0 && xVXsize && y>=0 && yVYsize) {
 if (object->Type == MEMBUF ||
 !VGLMouseFreeze(x, y, 1, 1, 0x8000 | color)) {
+  offset = (y * object->VXsize + x) * object->PixelBytes;
   switch (object->Type) {
+  case VIDBUF8S:
+  case VIDBUF16S:
+  case VIDBUF24S:
+  case VIDBUF32S:
+offset = VGLSetSegment(offset);
+/* FALLTHROUGH */
   case MEMBUF:
-  switch (object->PixelBytes) {
-  case 2:
-goto vidbuf16;
-  case 3:
-goto vidbuf24;
-  case 4:
-goto vidbuf32;
-  }
-  /* fallthrough */
   case VIDBUF8:
-object->Bitmap[y*object->VXsize+x]=((byte)color);
-break;
-  case VIDBUF8S:
-   object->Bitmap[VGLSetSegment(y*object->VXsize+x)]=((byte)color);
-   break;
   case VIDBUF16:
-vidbuf16:
   

Re: svn commit: r346176 - head/sys/sys

2019-09-03 Thread Bruce Evans

On Sat, 13 Apr 2019, Warner Losh wrote:


 Fix sbttons for values > 2s

 Add test against negative times. Add code to cope with larger values
 properly.

 Discussed with: bde@ (quite some time ago, for an earlier version)


I am unhappy with previous attempted fixes in this area, and still have large
local patches.

Old versions supported negative times.  This was broken in 2 stages:
- use a buggy inline conversion function instead of a working macro
- break negative times further when fixing overflow bugs in the inline
  function
- attempt to panic for negative times, but actually do nothing since
  this is in unreachable code.


Modified: head/sys/sys/time.h
==
--- head/sys/sys/time.h Sat Apr 13 04:42:17 2019(r346175)
+++ head/sys/sys/time.h Sat Apr 13 04:46:35 2019(r346176)
@@ -184,8 +184,18 @@ sbttobt(sbintime_t _sbt)
static __inline int64_t
sbttons(sbintime_t _sbt)
{
+   uint64_t ns;

-   return ((10 * _sbt) >> 32);


sbintime_t is a signed type so as to support negative times.  This function
returns a signed type so as to support negative times.

The original sloppy and fast version with a macro worked for all negative
times, modulo the assumption that right shifts propagate the sign bit.
It just did _sbt >> 32.

The above slower and more accurate version might have worked for negative
times similarly, but this is less clear.  E.g., if _sbt is -1 second, that
is 0x (-1) in the high 32 bits and 0 in the low 32 bits.
Multiplying this by 10**9 doesn't overflow since both terms are signed,
and gives a result near -1 in the high bits and the shift works before.
I think similarly for all negative values down to the overflow threshold
of about -2 seconds.

Similarly for the other functions -- the simple shifts just worked
(unportably), while all later versions have overflow and/or sign extension
bugs.


+#ifdef KASSERT
+   KASSERT(_sbt >= 0, ("Negative values illegal for sbttons: %jx", _sbt));
+#endif


KASSERT is never defined here except in code with style bugs.  In the
kernel, sys/time.h is never included directly except in code with style
bugs.  It is normally included as part of standard namespace pollution
in sys/param.h.  Namespace pollution defeats ifdefs like this.  KASSERT
is only defined in sys/systm.h (except...), so it is never defined when
sys/param.h includes sys/time.h (except in code with even worse style
bugs, such as including sys/systm.h unsorted before sys/systm.h...).

In userland, KASSERT is never defined here except in code with style bugs
(such as being chummy with the implementation and defining KASSERT to use
here) and in code to demonstrate the brokenness of this header (KASSERT is
in the application namespace, so the demonstration can define it as
'syntax error'.


+   ns = _sbt;


This corrupts the type from signed to unsigned.

This has no effect except to ensure breaking negative times.  E.g., if
the time is not negative, then the conversion doesn't change its value.
Ottherwise, the conversion prevents propagation of the sign bit.  E.g,
if the time is -1 then shifting right the signed value by 32 keeps it
as -1, but shifting right the unsigned value gives UINT32_MAX seconds =
UINT32_MAX * 10**9 nsec = about 1/4 of UINT64_MAX seconds.  Since this
and all other possible values in ns are less than 1/4 UINT64_MAX, then
are also less than INT64_MAX, so conversion back to a signed type doesn't
overflow them back to a negative value.


+   if (ns >= SBT_1S)
+   ns = (ns >> 32) * 10;
+   else
+   ns = 0;
+


Style bug (extra blank line).  In KNF, statements are separated by a
semilcolon and a single newline.  An extra newline is especially bad
when it is used to separate closely related statements like here.


+   return (ns + (10 * (_sbt & 0xu) >> 32));


This seems to be correct, except for its style bugs of spelling the U
suffix in lower case.  I don't like using the suffix, but the value
of plain 0x after promotion to the type of _sbt is unclear.


}

static __inline sbintime_t


Conversion in the opposite direction is more difficult and buggier.  I
currently use the following cut down version with only the most important
function fixed:

XX Index: time.h
XX ===
XX --- time.h   (revision 346046)
XX +++ time.h   (working copy)
XX @@ -200,8 +200,20 @@
XX  sb = (_ns / 10) * SBT_1S;
XX  _ns = _ns % 10;

These divisons are very slow on i386, and not very fast on amd64.  They
defeat the manual reductions to shifts and multiplications in the rest
of the code.  This case starts unnecessarily early (at 1 second instead
of at the overflow threshold of 4+ seconds).

XX  }
XX +#if 0
XX  /* 9223372037 = ceil(2^63 / 10) */
XX  sb += ((_ns * 9223372037ull) + 0x7fff) >> 31;


Re: svn commit: r346176 - head/sys/sys

2019-09-03 Thread Bruce Evans

On Sat, 13 Apr 2019, Bruce Evans wrote:


On Sat, 13 Apr 2019, Warner Losh wrote:


 Fix sbttons for values > 2s

 Add test against negative times. Add code to cope with larger values
 properly.

 Discussed with: bde@ (quite some time ago, for an earlier version)


I am unhappy with previous attempted fixes in this area, and still have large
local patches.
...

Modified: head/sys/sys/time.h
==
--- head/sys/sys/time.h Sat Apr 13 04:42:17 2019(r346175)
+++ head/sys/sys/time.h Sat Apr 13 04:46:35 2019(r346176)
@@ -184,8 +184,18 @@ sbttobt(sbintime_t _sbt)
static __inline int64_t
sbttons(sbintime_t _sbt)
{
+   uint64_t ns;

-   return ((10 * _sbt) >> 32);

* ...

+   ns = _sbt;
+   if (ns >= SBT_1S)
+   ns = (ns >> 32) * 10;
+   else
+   ns = 0;
+

...

+   return (ns + (10 * (_sbt & 0xu) >> 32));


Another style bug: extra parentheses moved from a useful place to a non-
useful place.  '*' has precedence over '>>', but this combination is
unusual so the old code emphasized it using parentheses.  '*' has
precedence over '+', and this combination is usual so it shouldn't be
emphasized using parentheses, but the new code does that and removes the
more useful parentheses.


}


sbttous() and sbttoms() are still broken.  sbtots() might be pessimized
since it calls sbttons with a 32-bit arg that doesn't need the above
complications (the compiler would be doing well to see that and replace
ns by 0 in the above calculations.

Another bug in the above and previous changes: ns is in the application
namespace.  Adding it defeats the care taken with naming the arg with
an underscore.  All inline functions in standard and sys headers have this
problem.  These are under __BSD_VISIBLE, but of course there is no
documentation that this reserves the names ns, etc.

Better fix based on looking at sbtots(): split _sbt into seconds and
nanoseconds unconditially and reassemble using simple expressions.
This is almost as efficient on 32-bit arches, since the seconds and
nanoseconds fit in 32 bits so reassembly uses 2 32x32 -> 64-bit
multiplications instead of 1 64x32 -> 64-bit multiplication.

static __inline int64_t
sbttons(sbintime_t _sbt)
{

#ifdef __tooslow
if (__predict_false(_sbt == INT64_MIN)
return (-1);/* round towards +-Inf to keep non-0 */
#endif
#ifdef __maybenottooslow
if (__predict_false(_sbt < 0))
return sbttons(-sbt);
#endif
return (10 * (_sbt >> 32) +
(10 * (_sbt & 0xU)) >> 32);   /* XXX rounding? 
*/
}

Handling negative values makes it about as messy and slow as the committed
version :-(.

Rounding is also a problem.  It is normal to round times down, but that
turns nonzero into zero which is bad for timeouts.  The version in my
previous reply always adds 1 mainly to avoid this.  Conversion to a
different representation and back gives double rounding down if rounding
is always done, so rarely gives the original value.  The file still has
phk's comment about rounding down being required, and the changes to the
sbintime conversion functions still ignore this.

Bruce


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346025 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Mon Apr  8 04:54:15 2019
New Revision: 346025
URL: https://svnweb.freebsd.org/changeset/base/346025

Log:
  Fix copying of MEMBUFs to MEMBUFs.  This case was implemented by using
  the same code as the VIDBUF8 case, so it only worked for depths <= 8.
  The 2 directions for copying between VIDBUFs and MEMBUFs worked by using
  a Read/Write organization which makes the destination a VIDBUF so the
  MEMBUF case was not reached, and the VIDBUF cases have already been fixed.
  
  Fix this by removing "optimizations" for the VIDBUF8 case so that the
  MEMBUF case can fall through to the general (non-segmented) case.  The
  optimizations were to duplicate code for the VIDBUF8 case so as to
  avoid 2 multiplications by 1 at runtime.  This optimization is not useful
  since the multiplications are not in the inner loop.
  
  Remove the same "optimization" for the VIDBUF8S case.  It was even less
  useful there since it duplicated more to do relatively less.

Modified:
  head/lib/libvgl/bitmap.c

Modified: head/lib/libvgl/bitmap.c
==
--- head/lib/libvgl/bitmap.cMon Apr  8 04:07:37 2019(r346024)
+++ head/lib/libvgl/bitmap.cMon Apr  8 04:54:15 2019(r346025)
@@ -136,16 +136,6 @@ WriteVerticalLine(VGLBitmap *dst, int x, int y, int wi
 }
 break;
   case VIDBUF8S:
-pos = dst->VXsize * y + x;
-while (width > 0) {
-  offset = VGLSetSegment(pos);
-  i = min(VGLAdpInfo.va_window_size - offset, width);
-  bcopy(line, dst->Bitmap + offset, i);
-  line += i;
-  pos += i;
-  width -= i;
-}
-break;
   case VIDBUF16S:
   case VIDBUF24S:
   case VIDBUF32S:
@@ -160,11 +150,8 @@ WriteVerticalLine(VGLBitmap *dst, int x, int y, int wi
   width -= i;
 }
 break;
-  case VIDBUF8:
   case MEMBUF:
-address = dst->Bitmap + dst->VXsize * y + x;
-bcopy(line, address, width);
-break;
+  case VIDBUF8:
   case VIDBUF16:
   case VIDBUF24:
   case VIDBUF32:
@@ -251,16 +238,6 @@ read_planar:
 }
 break;
   case VIDBUF8S:
-pos = src->VXsize * y + x;
-while (width > 0) {
-  offset = VGLSetSegment(pos);
-  i = min(VGLAdpInfo.va_window_size - offset, width);
-  bcopy(src->Bitmap + offset, line, i);
-  line += i;
-  pos += i;
-  width -= i;
-}
-break;
   case VIDBUF16S:
   case VIDBUF24S:
   case VIDBUF32S:
@@ -275,11 +252,8 @@ read_planar:
   width -= i;
 }
 break;
-  case VIDBUF8:
   case MEMBUF:
-address = src->Bitmap + src->VXsize * y + x;
-bcopy(address, line, width);
-break;
+  case VIDBUF8:
   case VIDBUF16:
   case VIDBUF24:
   case VIDBUF32:


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346024 - head/usr.sbin/vidcontrol

2019-09-03 Thread Bruce Evans
Author: bde
Date: Mon Apr  8 04:07:37 2019
New Revision: 346024
URL: https://svnweb.freebsd.org/changeset/base/346024

Log:
  Fix restoring the geometry when recovering from an error.  Just restore the
  previous geometry, and don't do extra work to calculate the default geometry
  so as to reset to that.

Modified:
  head/usr.sbin/vidcontrol/vidcontrol.c

Modified: head/usr.sbin/vidcontrol/vidcontrol.c
==
--- head/usr.sbin/vidcontrol/vidcontrol.c   Mon Apr  8 03:35:47 2019
(r346023)
+++ head/usr.sbin/vidcontrol/vidcontrol.c   Mon Apr  8 04:07:37 2019
(r346024)
@@ -171,9 +171,8 @@ revert(void)
else
ioctl(0, _IO('S', cur_info.video_mode_number), NULL);
if (cur_info.video_mode_info.vi_flags & V_INFO_GRAPHICS) {
-   size[0] = cur_info.video_mode_info.vi_width / 8;
-   size[1] = cur_info.video_mode_info.vi_height /
-   cur_info.console_info.font_size;
+   size[0] = cur_info.console_info.mv_csz;
+   size[1] = cur_info.console_info.mv_rsz;
size[2] = cur_info.console_info.font_size;
ioctl(0, KDRASTER, size);
}


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r345900 - head/sbin/fsck_msdosfs

2019-09-03 Thread Bruce Evans

On Fri, 5 Apr 2019, Ed Maste wrote:


On Fri, 5 Apr 2019 at 00:49, Rodney W. Grimes  wrote:





+static const u_char dot_name[] = {
+ '.', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' };
+static const u_char dotdot_name[] = {
+ '.', '.',' ',' ',' ',' ',' ',' ',' ',' ',' ' };
+


Does it make since to encode these as hex or octal constants,
one can not tell that those are different values in an easy
manner.  They all look like '.' in the diff, and probably
in most editors.


No, but it makes sense to write them as string constants.  They are just
the strings "." and ".." padded with spaces to length 11, except they
are not actually strings since they are not NUL terminated.  11 is for
8+3 msdos short file names.  These are not NUL terminated either, but
it should be easy to ignore the extra NUL given by the string constants.


They are all either '.' or ' ', the commas are just list separators.
IMO spaces after the commas would make it slightly easier to see.


The single quotes looking like commas indeed makes this hard to read.

Bruce


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r345853 - head/usr.bin/rctl

2019-09-03 Thread Bruce Evans

On Wed, 3 Apr 2019, Enji Cooper wrote:


On Apr 3, 2019, at 1:37 PM, Mateusz Guzik  wrote:

Author: mjg
Date: Wed Apr  3 20:37:14 2019
New Revision: 345853
URL: https://svnweb.freebsd.org/changeset/base/345853

Log:
 rctl: fix sysctl kern.racct.enable use after r341182

 The value was changed from int to bool. Since the new type
 is smaller, the rest of the variable in the caller was left
 unitialized.


Why not fix the bug?  It it was breaking the ABI by changing int to bool.
Churning int to bool is bad enough even when it doesn't break ABIs.


I hit a bug like this recently with capsicum-test. Do you think it makes sense 
to purge all of the memory or return -1/set EINVAL for reasons similar to this 
for newp?

[EINVAL]   A non-null newp is given and its specified length in
   newlen is too large or too small.


Purge?  That would break correct programs to not detect ABI mismatches
and kernel bugs.

One direction of this was broken almost 25 years ago in phk's rewrite
of sysctl.  I use the following fix (edited from my 16 year old 1483
line patch for mostly style bugs in kern_sysctl.c,  There are many
more now).

XX Index: kern_sysctl.c
XX ===
XX RCS file: /home/ncvs/src/sys/kern/kern_sysctl.c,v
XX retrieving revision 1.157
XX diff -u -2 -r1.157 kern_sysctl.c
XX --- kern_sysctl.c11 Jun 2004 02:20:37 -  1.157
XX +++ kern_sysctl.c11 Jun 2004 07:58:23 -
XX @@ -957,6 +949,13 @@
XX  if (!req->newptr)
XX  return 0;
XX -if (req->newlen - req->newidx < l)
XX +if (req->newlen - req->newidx != l) {
XX +if (req->newlen - req->newidx > l) {
XX +printf(
XX +"sysctl_new_kernel -- short write: %zu - %zu > %zu\n",
XX +req->newlen, req->newidx, l);
XX +Debugger("sysctl_new_kernel: short write");
XX +}
XX  return (EINVAL);
XX +}
XX  bcopy((char *)req->newptr + req->newidx, p, l);
XX  req->newidx += l;
XX @@ -1075,6 +1073,13 @@
XX  if (!req->newptr)
XX  return 0;
XX -if (req->newlen - req->newidx < l)
XX +if (req->newlen - req->newidx != l) {
XX +if (req->newlen - req->newidx > l) {
XX +printf(
XX +"sysctl_new_user -- short write: %zu - %zu > %zu\n",
XX +req->newlen, req->newidx, l);
XX +Debugger("sysctl_new_user: short write");
XX +}
XX  return (EINVAL);
XX +}
XX  error = copyin((char *)req->newptr + req->newidx, p, l);
XX  req->newidx += l;

IIRC, the error is still detected for short reads.  This seems to be the
case here.

More recently, I tried to fix the sysctl ABI so that applications don't
need to hard-code or probe for the size of integer variables to match
the size used by the current kernel.  Any size large enough to represent
the value should work.  E.g., for this bool, applications that use the
unchurned ABI write an int, and everything works provided the int can
be represented as a bool.

In the opposite direction, larger kernel variables can easily represent
smaller application variables, so there is no problem provided the
kernel does the correct conversions.  Currently it doesn't.  For short
writes, it writes to the lower bits and leaves garbage in the top bits.
Or maybe the reverse for big-endian.  Then it succeeds and doesn't
return the documented error -1/EINVAL.

My fix would break some probes.  It seems to be neccessary to probe using
reads, since writes would be destructive.  The application might try to
read into an int8_t variable.  This would succeed if the kernel variable
is intmax_t, provided the current value is between 0 and 127.  But
writing 128 or larger later won't work.  The applications can start the
probe with the maximum type intmax_t, but that will always work
(except for unsigned values), so the application might as well hard-code
use of intmax_t and waste a lot of space.

Most applications are currently broken by not probing at all.  This often
breaks ones like systat and top which report kernel variables whose size
often increases.  Errror handling in systat and top is still very broken:
- getsysctl() in systat detects all size mismatches but mishandles them
  by printing an error message and returning garbage.  It mishandles
  even errors detected by the kernel similarly, except the garbage is
  less processed if sysctlbyname() fails.  It also has many style bugs
  (function type on the same line as the function name; initialization
  in declaration; no blank line after declaration; excessive braces;
  casts to unsigned long to print size_t's since %zu has only been
  standard for 20 years; not using the BSD spelling u_long in these
  casts).
- top uses the same getsysctl() wrapper as systat, but quits after an
  error and is missing the style bugs except for the the 

Re: svn commit: r345807 - head/usr.bin/top

2019-09-03 Thread Bruce Evans

On Tue, 2 Apr 2019, Dimitry Andric wrote:


Author: dim
Date: Tue Apr  2 18:01:54 2019
New Revision: 345807
URL: https://svnweb.freebsd.org/changeset/base/345807

Log:
 Fix regression in top(1) after r344381, causing informational messages
 to no longer be displayed.  This was because the reimplementation of
 setup_buffer() did not copy the previous contents into any reallocated
 buffer.

 Reported by:   James Wright 
 PR:236947
 MFC after: 3 days

Modified:
 head/usr.bin/top/display.c

Modified: head/usr.bin/top/display.c
==
--- head/usr.bin/top/display.c  Tue Apr  2 17:51:28 2019(r345806)
+++ head/usr.bin/top/display.c  Tue Apr  2 18:01:54 2019(r345807)
@@ -1347,7 +1347,8 @@ i_uptime(struct timeval *bt, time_t *tod)
static char *
setup_buffer(char *buffer, int addlen)
{
-size_t len;
+size_t len, old_len;
+char *new_buffer;

setup_buffer_bufsiz = screen_width;
if (setup_buffer_bufsiz < SETUPBUFFER_MIN_SCREENWIDTH)
@@ -1355,13 +1356,18 @@ setup_buffer(char *buffer, int addlen)
setup_buffer_bufsiz = SETUPBUFFER_MIN_SCREENWIDTH;
}

-free(buffer);
len = setup_buffer_bufsiz + addlen + SETUPBUFFER_REQUIRED_ADDBUFSIZ;
-buffer = calloc(len, sizeof(char));
-if (buffer == NULL)
+new_buffer = calloc(len, sizeof(char));
+if (new_buffer == NULL)
{
errx(4, "can't allocate sufficient memory");
}
+if (buffer != NULL)
+{
+   old_len = strlen(buffer);
+   memcpy(new_buffer, buffer, old_len < len - 1 ? old_len : len - 1);
+   free(buffer);
+}

-return buffer;
+return new_buffer;
}


Looks like realloc() hasn't been invented yet.

realloc() wouldn't clear the new part of the buffer, so a memset() or at
least setting the first byte in a new buffer (starting with buffer == NULL
might be needed).

The above has some bugs when the new buffer is smaller the old buffer:
- when old_len < len - 1, the new buffer has no space for the old buffer
  including its NUL terminator, so the new buffer is left unterminated
  after blind truncation
- when old_len == len - 1, the new buffer has no space for the NUL
  terminator, so the new buffer is left unterminated after not overrunning
  it by copying the NUL terminator
- when old_len > len - 1, the new buffer is NUL terminated in an obfuscated
  way (calloc() has filled it with NULs and the memcpy() doesn't overwrite
  them all).

Bruce


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r345696 - head/lib/libvgl

2019-09-03 Thread Bruce Evans

On Sun, 31 Mar 2019, Konstantin Belousov wrote:


On Sun, Mar 31, 2019 at 10:27:54PM +1100, Bruce Evans wrote:

On Sat, 30 Mar 2019, Konstantin Belousov wrote:


On Sat, Mar 30, 2019 at 03:24:40PM +1100, Bruce Evans wrote:

On Fri, 29 Mar 2019, Konstantin Belousov wrote:


On Fri, Mar 29, 2019 at 03:57:09PM +, Bruce Evans wrote:

Author: bde
Date: Fri Mar 29 15:57:08 2019
New Revision: 345696
URL: https://svnweb.freebsd.org/changeset/base/345696

Log:
  Fix endless loops for handling SIGBUS and SIGSEGV.

  r80270 has the usual wrong fix for unsafe signal handling -- just set
  a flag and return to let an event loop check the flag and do safe
  handling.  This never works for signals like SIGBUS and SIGSEGV that
  repeat and works poorly for others unless the application has an event
  loop designed to support this.

  For these signals, clean up unsafely as before, except for arranging that
  nested signals are fatal and forcing a nested signal if the cleanup doesn't
  cause one.

Modified:
  head/lib/libvgl/main.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Fri Mar 29 15:20:48 2019(r345695)
+++ head/lib/libvgl/main.c  Fri Mar 29 15:57:08 2019(r345696)
...
@@ -107,14 +107,22 @@ struct vt_mode smode;
 }

 static void
-VGLAbort(int arg __unused)
+VGLAbort(int arg)
 {
+  sigset_t mask;
+
   VGLAbortPending = 1;
   signal(SIGINT, SIG_IGN);
   signal(SIGTERM, SIG_IGN);
-  signal(SIGSEGV, SIG_IGN);
-  signal(SIGBUS, SIG_IGN);
   signal(SIGUSR2, SIG_IGN);
+  if (arg == SIGBUS || arg == SIGSEGV) {
+signal(arg, SIG_DFL);
+sigemptyset();
+sigaddset(, arg);
+sigprocmask(SIG_UNBLOCK, , NULL);
+VGLEnd();
+kill(getpid(), arg);

This of course misses the siginfo information from the real fault.


It is in the nested signal frame.


Why SIGBUS/SIGSEGV are caught at all ?


Otherwise, the screen is left in an application mode that the kernel
doesn't support (except to not write to the screen, so that the
application has full control).


Also, the keyboard may be left in a strange state.  Usually this is no
worse than termios raw mode, but it may be raw scancodes.  In raw scancodes
mode, Alt-Fn to switch to another vty to fix the problem.  libvgl disables
switching to another vty without going through a libvgl handler anyway.
The combination is usually enough to break switching to vty0 to run ddb,
though that should work for at least breakpoints in the kernel.  IIRC,
sc_cngrab() switches the keyboard mode, and my version of it restores
ignoring of the anti-switch flag.


...
I am more about not doing kill(2) from the handler, instead do plain
return to the context which caused the original signal.


That won't work well for SIGBUS's and SIGSEGV's related to the library.
If the above cleanup is not done, then it is too hard to debug the problem,
and if the above cleanup is done then it is impossible to debug the original
problem if it was for and invalid access in libvgl code.

The latter is a problem for the above cleanup too -- the cleanup clobbers
the libvgl state.

However, I could do a more limited cleanup of just restoring the screen and
keyboard state using ioctls.  ioctl() isn't async-signal safe in POSIX, but
most ioctls are async-signal safe in practice provided they don't use
global variables that were set too recently or too non-atomically.
VGLEnd() uses main globals established by VGLInit().  It depends on program
order which is not guaranteed in signal handlers for testing the flags set
by initialization.  The cleanup now also does:
- screen clearing.  This breaks debugging and is dangerous if the bug is
   in screen clearing.  Screen clearing is also very slow, and belongs
   in the kernel.  It is now done 4 times per libvgl use, but its
   slowness is limited by the kernel not clearing properly and the
   kernel not allowing the application to mmap() the whole physical
   frame buffer in some versions of FreeBSD (this breaks panning).
- munmap().  This breaks debugging.
- free() of backing store buffer and the main VGLDisplay data.  This breaks
   debugging and is unnecessary if we are going to exit.


You can only try to do async-safe calls from SIGSEGV handler, to not
break a limited chances to success. Also you should not modify in-memory
state for the library, for the same reason, and then it fits your goal
of keeping the state intact for debugging. Then you should return to
re-create the original situation causing and not kill(2).


That is what I suggested in "however".  However2, it is extra work to write
a different exit path.  When running the program directly under gdb, you
also have to tell gdb to not stop at any caught signal, since the screen
will be unusable then.


I find it weird to try to debug mode-switched code without serial console.


Running gdb on a remote system via a remote shell works almost as well.
It is inconvenient to

Re: svn commit: r345696 - head/lib/libvgl

2019-09-03 Thread Bruce Evans

On Sun, 31 Mar 2019, Konstantin Belousov wrote:


On Mon, Apr 01, 2019 at 12:04:45AM +1100, Bruce Evans wrote:

Serial consoles are not always available.

Better debuggers switch the screen mode as necessary.

I recently noticed another mode switching problem.  On i386, cycling
through about 50 modes to test them all takes a small fraction of a
second for each mode switch (done directly in syscons or by a vm86
BIOS call) even when the monitor takes too long to resync (the monitor
resyncs are coalesced, so 50 resyncs take about 5 seconds instead of
250).  But on amd64, mode switches to VESA mode and back take about
20 seconds.  They are not coalesced, and most of the system is stopped
waiting for them (at least remote network access is stopped).  amd64
can't use vm86, so it emulates BIOS calls.  Why does the emulation stop
the rest of the system and take so long?


How many CPUs do you have ?


8 on the machine that shows the problem -- an underdesktop with Haswell
graphics.

A laptop with Sandybridge graphics only waits for 0.25 seconds (sys time)
I don't know if it stops the system for that long (it would be 2 blockages
for half that long).  The laptop's integrated screen also syncs instantly.
The undermydesktop has an LED screen connected by DVI-D.


x86bios.c x86bios_call() does spinlock_enter() around emulator calls.
This disables interrupts.

If you have only one CPU, the consequences are obvious. If you have
more than one, then perhaps next IPI targeted to this CPU blocks the
originator, if IPI requires ack, which typically true for most common
TLB shutdown IPIs. Then both this CPU and originator block any other CPU
trying to send an IPI.


Serial console interrupts on another CPU work to enter ddb instantly and
show the emulator stopped.

Binding drivers to CPU unimproves scheduling in general, and here it might
result in iflib waiting for the CPU with interrupts disabled, but usually
the CPU with interrupts disabled is not the one(s) bound to by iflib, and
binding the graphics program to one not used by iflib doesn't help.

Removing the spinlock_enter/exit() using ddb makes no difference.


For this reason I have to come through several hoops to not disable
interrupts for duration of EFI runtime calls, otherwise spinlocks die
due to 'spin lock held too long' on other CPUs.


I turn off the 'spin lock held too long' panics in my fixes for console
and message buffer i/o.  Printing "spin lock held too long\n" takes 120
seconds at 2 bps.  Draining 16K of buffered messages takes 81920 seconds
at 2 bps.  The main fix is to cancel the timeouts here while any console
driver is making progress (hopefully printing messages about the actual
error).  2 bps is too slow to be useful, but it gives a good stress test
and a check that the timeouts are scaled properly by the console speed.

Disabling interrupts might be FUD.  vm86 on i386 only uses critical_enter()
in addition to its sleep lock.  But this is bad for scheduling too.

Bruce


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r345696 - head/lib/libvgl

2019-09-03 Thread Bruce Evans

On Sat, 30 Mar 2019, Konstantin Belousov wrote:


On Sat, Mar 30, 2019 at 03:24:40PM +1100, Bruce Evans wrote:

On Fri, 29 Mar 2019, Konstantin Belousov wrote:


On Fri, Mar 29, 2019 at 03:57:09PM +, Bruce Evans wrote:

Author: bde
Date: Fri Mar 29 15:57:08 2019
New Revision: 345696
URL: https://svnweb.freebsd.org/changeset/base/345696

Log:
  Fix endless loops for handling SIGBUS and SIGSEGV.

  r80270 has the usual wrong fix for unsafe signal handling -- just set
  a flag and return to let an event loop check the flag and do safe
  handling.  This never works for signals like SIGBUS and SIGSEGV that
  repeat and works poorly for others unless the application has an event
  loop designed to support this.

  For these signals, clean up unsafely as before, except for arranging that
  nested signals are fatal and forcing a nested signal if the cleanup doesn't
  cause one.

Modified:
  head/lib/libvgl/main.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Fri Mar 29 15:20:48 2019(r345695)
+++ head/lib/libvgl/main.c  Fri Mar 29 15:57:08 2019(r345696)
...
@@ -107,14 +107,22 @@ struct vt_mode smode;
 }

 static void
-VGLAbort(int arg __unused)
+VGLAbort(int arg)
 {
+  sigset_t mask;
+
   VGLAbortPending = 1;
   signal(SIGINT, SIG_IGN);
   signal(SIGTERM, SIG_IGN);
-  signal(SIGSEGV, SIG_IGN);
-  signal(SIGBUS, SIG_IGN);
   signal(SIGUSR2, SIG_IGN);
+  if (arg == SIGBUS || arg == SIGSEGV) {
+signal(arg, SIG_DFL);
+sigemptyset();
+sigaddset(, arg);
+sigprocmask(SIG_UNBLOCK, , NULL);
+VGLEnd();
+kill(getpid(), arg);

This of course misses the siginfo information from the real fault.


It is in the nested signal frame.


Why SIGBUS/SIGSEGV are caught at all ?


Otherwise, the screen is left in an application mode that the kernel
doesn't support (except to not write to the screen, so that the
application has full control).


Also, the keyboard may be left in a strange state.  Usually this is no
worse than termios raw mode, but it may be raw scancodes.  In raw scancodes
mode, Alt-Fn to switch to another vty to fix the problem.  libvgl disables
switching to another vty without going through a libvgl handler anyway.
The combination is usually enough to break switching to vty0 to run ddb,
though that should work for at least breakpoints in the kernel.  IIRC,
sc_cngrab() switches the keyboard mode, and my version of it restores
ignoring of the anti-switch flag.


...
I am more about not doing kill(2) from the handler, instead do plain
return to the context which caused the original signal.


That won't work well for SIGBUS's and SIGSEGV's related to the library.
If the above cleanup is not done, then it is too hard to debug the problem,
and if the above cleanup is done then it is impossible to debug the original
problem if it was for and invalid access in libvgl code.

The latter is a problem for the above cleanup too -- the cleanup clobbers
the libvgl state.

However, I could do a more limited cleanup of just restoring the screen and
keyboard state using ioctls.  ioctl() isn't async-signal safe in POSIX, but
most ioctls are async-signal safe in practice provided they don't use
global variables that were set too recently or too non-atomically.
VGLEnd() uses main globals established by VGLInit().  It depends on program
order which is not guaranteed in signal handlers for testing the flags set
by initialization.  The cleanup now also does:
- screen clearing.  This breaks debugging and is dangerous if the bug is
  in screen clearing.  Screen clearing is also very slow, and belongs
  in the kernel.  It is now done 4 times per libvgl use, but its
  slowness is limited by the kernel not clearing properly and the
  kernel not allowing the application to mmap() the whole physical
  frame buffer in some versions of FreeBSD (this breaks panning).
- munmap().  This breaks debugging.
- free() of backing store buffer and the main VGLDisplay data.  This breaks
  debugging and is unnecessary if we are going to exit.

Bruce


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r345696 - head/lib/libvgl

2019-09-03 Thread Bruce Evans

On Fri, 29 Mar 2019, Konstantin Belousov wrote:


On Fri, Mar 29, 2019 at 03:57:09PM +, Bruce Evans wrote:

Author: bde
Date: Fri Mar 29 15:57:08 2019
New Revision: 345696
URL: https://svnweb.freebsd.org/changeset/base/345696

Log:
  Fix endless loops for handling SIGBUS and SIGSEGV.

  r80270 has the usual wrong fix for unsafe signal handling -- just set
  a flag and return to let an event loop check the flag and do safe
  handling.  This never works for signals like SIGBUS and SIGSEGV that
  repeat and works poorly for others unless the application has an event
  loop designed to support this.

  For these signals, clean up unsafely as before, except for arranging that
  nested signals are fatal and forcing a nested signal if the cleanup doesn't
  cause one.

Modified:
  head/lib/libvgl/main.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Fri Mar 29 15:20:48 2019(r345695)
+++ head/lib/libvgl/main.c  Fri Mar 29 15:57:08 2019(r345696)
...
@@ -107,14 +107,22 @@ struct vt_mode smode;
 }

 static void
-VGLAbort(int arg __unused)
+VGLAbort(int arg)
 {
+  sigset_t mask;
+
   VGLAbortPending = 1;
   signal(SIGINT, SIG_IGN);
   signal(SIGTERM, SIG_IGN);
-  signal(SIGSEGV, SIG_IGN);
-  signal(SIGBUS, SIG_IGN);
   signal(SIGUSR2, SIG_IGN);
+  if (arg == SIGBUS || arg == SIGSEGV) {
+signal(arg, SIG_DFL);
+sigemptyset();
+sigaddset(, arg);
+sigprocmask(SIG_UNBLOCK, , NULL);
+VGLEnd();
+kill(getpid(), arg);

This of course misses the siginfo information from the real fault.


It is in the nested signal frame.


Why SIGBUS/SIGSEGV are caught at all ?


Otherwise, the screen is left in an application mode that the kernel
doesn't support (except to not write to the screen, so that the
application has full control).

Of course, it is bad for libraries to catch signals.  The man page warns
about installing signal handlers and trying to call VGLEnd() and exit(3)
[from the signal handler] to end the program, although it is important
to use VGLEnd() to end the program.  I haven't tried installing signal
handlers in programs, but my main application is another graphics library
that wraps libvgl, and it installs an atexit() handler which calls its
cleanup function which calls VGLEnd().  libvgl should do the same.  The
cleanup is safe in exit() provided calling exit() is safe.

The man page has general nonsense recommending setting a flag and not
terminating the program in signal handlers.  This was added in the same
commit that completely broke the SIGBUS and SIGSEGV handling using this
method.  A much longer lesson is needed to describe how to use this
method correctly.  SA_RESTART must be turned off for all signals, and
this gives the complexity of handling EINTR returns from all syscalls
affected by SA_RESTART ...

The man page has almost enough details about which signals the library
catches.  It doesn't mention SIGUSR1 (used for screen switches) or
SIGUSR2 (used for mouse signals).  I plan to add use of SIGIO to fix
busy-waiting for keyboard events.  select() might work for the keyboard,
but I doubt that it works for the mouse.

What should happen is if the application installs signal handlers and
does unsafe things not including calling VGLEnd(), then nested SIGBUS's
and SIGSEGV's should reach the above cleanup.  Applications should not
catch SIGBUS or SIGSEGV unless they can clean up better than the above.
It is possible to clean up better than the above, but not in applications.
The above can check a soft signal mask flag like the one set by INTOFF()
and not do so much when it is set.  When it is not set, I think restoring
the screen mode is safe in signal handlers, and only things like free()
and printf() are not safe in signal handlers.




+  }
 }

 static void




Bruce


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r345695 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Fri Mar 29 15:20:48 2019
New Revision: 345695
URL: https://svnweb.freebsd.org/changeset/base/345695

Log:
  Fix races in mouse signal handling almost properly using the INTOFF/INTON
  method as in /bin/sh.
  
  We still do technically undefined things in the signal handler, but it
  is safe in practice to access state that is protected by INTOFF/INTON.
  
  In a recent commit, I sprinkled VGLMouseFrozen++/-- operations in
  places that need INTOFF/INTON.  This prevented clobbering of pixels
  under the mouse, but left mouse signals deferred for too long.  It is
  necessary to call the signal handler when the count goes to 0.  Old
  versions did this in the unfreeze function, but didn't block actual
  signals, so the signal handler raced itself.  The sprinkled operations
  reduced the races, but when then worked to block a race they left
  signals deferred for too long.
  
  Use INTOFF/INTON to fix complete loss of mouse signals while reading
  the mouse status.  Clobbering of the state was prevented by SIG_IGN'ing
  mouse signals, but that has a high overhead and broke more than it
  fixed by losing mouse signals completely.  sigprocmask() works to block
  signals without losing them completely, but its overhead is also too
  high.
  
  libvgl's mouse signal handling is often worse than none.  Applications
  can't block waiting for a mouse or keyboard or other event, but have
  to busy-wait.  The SIG_IGN's lost about half of all mouse events while
  busy-waiting for mouse events.

Modified:
  head/lib/libvgl/mouse.c

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Fri Mar 29 15:07:00 2019(r345694)
+++ head/lib/libvgl/mouse.c Fri Mar 29 15:20:48 2019(r345695)
@@ -86,12 +86,19 @@ static byte map[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE*4];
 static VGLBitmap VGLMouseSave = 
 VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, map);
 static int VGLMouseVisible = 0;
-static int VGLMouseFrozen = 0;
 static int VGLMouseShown = 0;
 static int VGLMouseXpos = 0;
 static int VGLMouseYpos = 0;
 static int VGLMouseButtons = 0;
+static volatile sig_atomic_t VGLMintpending;
+static volatile sig_atomic_t VGLMsuppressint;
 
+#defineINTOFF()(VGLMsuppressint++)
+#defineINTON() do {
\
+   if (--VGLMsuppressint == 0 && VGLMintpending) \
+   VGLMouseAction(0);  \
+   } while (0)
+
 void
 VGLMousePointerShow()
 {
@@ -102,7 +109,7 @@ VGLMousePointerShow()
   int i, pos, pos1;
 
   if (!VGLMouseVisible) {
-VGLMouseFrozen++;
+INTOFF();
 VGLMouseVisible = 1;
 crtcidx = inb(0x3c4);
 crtcval = inb(0x3c5);
@@ -125,7 +132,7 @@ VGLMousePointerShow()
 outb(0x3c5, crtcval);
 outb(0x3ce, gdcidx);
 outb(0x3cf, gdcval);
-VGLMouseFrozen--;
+INTON();
   }
 }
 
@@ -135,7 +142,7 @@ VGLMousePointerHide()
   byte crtcidx, crtcval, gdcidx, gdcval;
 
   if (VGLMouseVisible) {
-VGLMouseFrozen++;
+INTOFF();
 VGLMouseVisible = 0;
 crtcidx = inb(0x3c4);
 crtcval = inb(0x3c5);
@@ -147,7 +154,7 @@ VGLMousePointerHide()
 outb(0x3c5, crtcval);
 outb(0x3ce, gdcidx);
 outb(0x3cf, gdcval);
-VGLMouseFrozen--;
+INTON();
   }
 }
 
@@ -173,10 +180,13 @@ VGLMouseAction(int dummy) 
 {
   struct mouse_info mouseinfo;
 
-  if (VGLMouseFrozen) {
-VGLMouseFrozen += 8;
+  if (VGLMsuppressint) {
+VGLMintpending = 1;
 return;
   }
+again:
+  INTOFF();
+  VGLMintpending = 0;
   mouseinfo.operation = MOUSE_GETINFO;
   ioctl(0, CONS_MOUSECTL, );
   if (VGLMouseShown == VGL_MOUSESHOW)
@@ -186,6 +196,15 @@ VGLMouseAction(int dummy)  
   VGLMouseButtons = mouseinfo.u.data.buttons;
   if (VGLMouseShown == VGL_MOUSESHOW)
 VGLMousePointerShow();
+
+  /* 
+   * Loop to handle any new (suppressed) signals.  This is INTON() without
+   * recursion.  !SA_RESTART prevents recursion in signal handling.  So the
+   * maximum recursion is 2 levels.
+   */
+  VGLMsuppressint = 0;
+  if (VGLMintpending)
+goto again;
 }
 
 void
@@ -248,11 +267,11 @@ VGLMouseInit(int mode)
 int
 VGLMouseStatus(int *x, int *y, char *buttons)
 {
-  signal(SIGUSR2, SIG_IGN);
+  INTOFF();
   *x =  VGLMouseXpos;
   *y =  VGLMouseYpos;
   *buttons =  VGLMouseButtons;
-  signal(SIGUSR2, VGLMouseAction);
+  INTON();
   return VGLMouseShown;
 }
 
@@ -261,7 +280,7 @@ VGLMouseFreeze(int x, int y, int width, int hight, u_l
 {
   int i, xstride, ystride;
 
-VGLMouseFrozen++;
+INTOFF();
 if (width > 1 || hight > 1 || (color & 0xc000) == 0) { /* bitmap */
   if (VGLMouseShown == 1) {
 int overlap;
@@ -311,13 +330,8 @@ VGLMouseFreeze(int x, int y, int width, int hight, u_l
 void
 VGLMouseUnFreeze()
 {
-  if (VGLMouseFrozen > 8) {
-VGLMouseFrozen = 0;
-VGLMouseAction(0);
-  }
-  else {
-   

Re: svn commit: r345680 - head/sys/conf

2019-09-03 Thread Bruce Evans

On Thu, 28 Mar 2019, Ravi Pokala wrote:


-Original Message-
From:  on behalf of Kyle Evans 

Date: 2019-03-28, Thursday at 21:00
To: , , 

Subject: svn commit: r345680 - head/sys/conf


Author: kevans
Date: Fri Mar 29 04:00:46 2019
New Revision: 345680
URL: https://svnweb.freebsd.org/changeset/base/345680

Log:
  NOTES: Use non-default value for BOOT_TAG


Why?

(I was on IRC when jhb debugged this, but I didn't quite get it; and of course 
lots of us *weren't* on IRC at the time.)


Because NOTES is primarily for generating LINT, and LINT's reason for
existence is to test as many cases as possible.  Testing the default cases
again is not very useful, so by convention NOTES never configures defaults,
except of course where it is broken.  This commit is to fix 1 broken place.

Not repeating the default is also good for NOTES' secondary purpose of
documentation.  Defaults are easy to find by grepping the source code for
them if there is no documentation.  Changing defaults to valid and useful
values requires understanding more of the source if there is no documentation.


Modified: head/sys/conf/NOTES
==
--- head/sys/conf/NOTES Fri Mar 29 03:25:20 2019(r345679)
+++ head/sys/conf/NOTES Fri Mar 29 04:00:46 2019(r345680)
@@ -150,7 +150,7 @@ options BOOTHOWTO=RB_MULTIPLE
 #
 # Default boot tag; may use 'kern.boot_tag' loader tunable to override.  The
 # current boot's tag is also exposed via the 'kern.boot_tag' sysctl.
-optionsBOOT_TAG=\"---<>---\"
+optionsBOOT_TAG=\"\"


Useful variations are not always easy to invent.  I usually just add 1 for
numeric values.  This example is useful.  It kills the boot tag.  It gives
an empty tag, and the kernel does extra work to avoid printing a newline
after an empty tag.


 # Maximum boot tag size the kernel's static buffer should accomodate.  Maximum
 # size for both BOOT_TAG and the assocated tunable.
 optionsBOOT_TAG_SZ=32


This bug remains unfixed.  32 is the default.  This option shouldn't exist.
Instead, just use size strlen(BOOT_TAG) + 1 for the static string and keep
the dynamic string in the environment.  The string is only used once, and
msgbufinit() already has to check both the static string and the environment
to find the right string (it does this by fetching the dynamic string to
overwrite the static string, but it is easier to not use a tunable or
support a sysctl and just keep the dynamic string in the environment).

Bruce


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r345680 - head/sys/conf

2019-09-03 Thread Bruce Evans

On Fri, 29 Mar 2019, Alexey Dokuchaev wrote:


On Fri, Mar 29, 2019 at 05:40:05PM +1100, Bruce Evans wrote:

...
-optionsBOOT_TAG=\"---<>---\"
+optionsBOOT_TAG=\"\"


Useful variations are not always easy to invent.  I usually just add 1 for
numeric values.  This example is useful.  It kills the boot tag.  It gives
an empty tag, and the kernel does extra work to avoid printing a newline
after an empty tag.


That's a nice idea, thanks Bruce.  I always had to revert commits that had
added this stupid boot tag; if empty tag does not imply a newline, then it
makes things much easier.

./danfe

P.S.  Boot tag of a healthy human is "Copyright (c) 1992-2018 The FreeBSD
Project".


Actually, there are ordering problems.  After fixing lost messages, I get
for the simplest case of a non-verbose cold boot:

XX Mar 29 19:14:08 gamplex syslogd: kernel boot file is /kernel

This boot file message is the first one.  I often grep for it, so as to
ignore messages for previous boots.

XX Mar 29 19:14:08 gamplex kernel: ---<>---

This is almost first.

XX Mar 29 19:14:08 gamplex kernel: Test of early printf to msgbuf
XX Mar 29 19:14:08 gamplex kernel: Test of early printf to console

Tests for my fixes.  msgbufinit() is called early and uses a statically
allocated buffer until the dynamic message buffer is mapped.  Early messages
are thus not lost for the message buffer.  They may be lost for the
console.

XX Mar 29 19:14:08 gamplex kernel: GDB: debug ports: sio
XX Mar 29 19:14:08 gamplex kernel: GDB: current port: sio
XX Mar 29 19:14:08 gamplex kernel: KDB: debugger backends: ddb gdb
XX Mar 29 19:14:08 gamplex kernel: KDB: current backend: ddb

Standard early messages if DDB is configured.

XX Mar 29 19:14:08 gamplex kernel: WARNING: loader(8) metadata is missing!

I don't use loader on i386, and am reminded that I don't like it by this
warning.

XX Mar 29 19:14:08 gamplex kernel: Copyright (c) 1992-2019 The FreeBSD Project.

Finally the copyright message.  The source code still obfuscates the order
of this using SYSINIT(), and on x86 and powerpc still has a bogus "Good
{morning,afternoon,evening, night}" comment that isn't even attached to its
code (the printf() of the message).  The comment is in cpu_startup()
which runs at SI_SUB_CPU, SI_ORDER_FIRST.  This is much later than printing
the copyright, which runs at SI_SUB_COPYRIGHT.  In between, there are SUBs
for VM, KMEM, HYPERISOR, WITNESS, MTX_POOL_DYNAMIC, LOCK, EVENTHANDLER,
VNET_PRELINK and KLD.  Before COPYRIGHT, there are only DUMMY, DONE and
TUNABLES under sysinit, but lots more in early initialization including
early console use for the above messages and ddb.  The comment on
SI_SUB_COPYRIGHT wrongly says that it is for the first use of the console.

Booting with -v gives many more early messages that are usually lost.  E.g.,
ones about SMAP on x86.

Warm boots sometimes give a dynamic message buffer that is actually useful.
To be useful, it must be retained at boot.  Otherwise, it is easier to
put the message buffer in the bss.

The dynamic message buffer only works for me on amd64 and i386 with pae_mode=1
(and probably also more than 4GB RAM).  Otherwise, it is below 4GB and the
BIOS scribbles on it (fairly sparsely, but it doesn't have enough error
correcting to recover).  Recovering it fixes loss of the last few messages
for the previous boot, but risks doubling of non-lost messages.  The BOOT
tags are useful for seeing where the new messages start.

Everything usually works as well as possible:

XX Mar 25 02:59:49 iotaplex syslogd: exiting on signal 15

The use of an amd64 kernel a few days ago was terminated by turning the
system off.  Messages printed after killing syslogd were lost.

XX Mar 29 21:33:49 iotaplex syslogd: kernel boot file is /boot/kernel/kernel
XX Mar 29 21:33:49 iotaplex kernel: ---<>---
XX Mar 29 21:33:49 iotaplex kernel: Test of early printf to msgbuf
XX Mar 29 21:33:49 iotaplex kernel: GDB: debug ports: sio
XX Mar 29 21:33:49 iotaplex kernel: GDB: current port: sio
XX Mar 29 21:33:49 iotaplex kernel: KDB: debugger backends: ddb gdb
XX Mar 29 21:33:49 iotaplex kernel: KDB: current backend: ddb
XX Mar 29 21:33:49 iotaplex kernel: Copyright (c) 1992-2019 The FreeBSD Project.

Cold boot of the same kernel today (actually, i386 was running before this,
but the boot was cold enough for the message buffer).

XX ...
XX Mar 29 21:34:32 iotaplex syslogd: exiting on signal 15

As usual, messages printed after killing syslogd are not logged properly...

XX Mar 29 21:35:55 iotaplex syslogd: kernel boot file is /boot/kernel/kernel

Warm boot of the same amd64 kernel.

XX Mar 29 21:35:55 iotaplex kernel: Waiting (max 60 seconds) for system process 
`vnlru' to stop... done
XX Mar 29 21:35:55 iotaplex kernel: Waiting (max 60 seconds) for system process `syncer' to stop... 
XX Mar 29 21:35:55 iotaplex kernel: Syncing disks, vnodes remaining... 0 0 0 done

XX Mar 29 21:35:55 i

svn commit: r345698 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Fri Mar 29 16:30:19 2019
New Revision: 345698
URL: https://svnweb.freebsd.org/changeset/base/345698

Log:
  Fix restoring to graphics modes in VGLEnd().
  
  Correct restoring was only attempted for mode 258 (800x600x4 P).  (This
  was the only useful graphics mode supported in the kernel until 10-15
  years ago, and is still the only one explicitly documented in the man
  page).  The comment says that it is the geometry (subscreen size) that
  is restored, but it seems to only be necessary to restore the font
  size, with the geometry only needed since it is set by the same ioctl.
  The font size was not restored for this mode, but was forced to 16.
  
  For other graphics modes, the font size was clobbered to 0.  This
  confuses but doesn't crash the kernel (font size 0 gives null text).
  This confuses and crashes vidcontrol.  The only way to recover was to
  use vidcontrol to set the mode to any text mode on the way back to the
  original graphics mode.
  
  vidcontrol gets this wrong in the opposite way when backing out of
  changes after an error.  It restores the font size correctly, but
  forces the geometry to the full screen size.

Modified:
  head/lib/libvgl/main.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Fri Mar 29 16:05:30 2019(r345697)
+++ head/lib/libvgl/main.c  Fri Mar 29 16:30:19 2019(r345698)
@@ -61,12 +61,14 @@ static int VGLAbortPending;
 static int VGLOnDisplay;
 static unsigned int VGLCurWindow;
 static int VGLInitDone = 0;
+static video_info_t VGLOldModeInfo;
 static vid_info_t VGLOldVInfo;
 
 void
 VGLEnd()
 {
 struct vt_mode smode;
+  int size[3];
 
   if (!VGLInitDone)
 return;
@@ -81,18 +83,15 @@ struct vt_mode smode;
 munmap(VGLMem, VGLAdpInfo.va_window_size);
   }
 
-  if (VGLOldMode >= M_VESA_BASE) {
-/* ugly, but necessary */
+  if (VGLOldMode >= M_VESA_BASE)
 ioctl(0, _IO('V', VGLOldMode - M_VESA_BASE), 0);
-if (VGLOldMode == M_VESA_800x600) {
-  int size[3];
-  size[0] = VGLOldVInfo.mv_csz;
-  size[1] = VGLOldVInfo.mv_rsz;
-  size[2] = 16;
-  ioctl(0, KDRASTER, size);
-}
-  } else {
+  else
 ioctl(0, _IO('S', VGLOldMode), 0);
+  if (VGLOldModeInfo.vi_flags & V_INFO_GRAPHICS) {
+size[0] = VGLOldVInfo.mv_csz;
+size[1] = VGLOldVInfo.mv_rsz;
+size[2] = VGLOldVInfo.font_size;;
+ioctl(0, KDRASTER, size);
   }
   ioctl(0, KDDISABIO, 0);
   ioctl(0, KDSETMODE, KD_TEXT);
@@ -165,12 +164,13 @@ VGLInit(int mode)
   if (ioctl(0, CONS_MODEINFO, ))   /* FBIO_MODEINFO */
 return -1;
 
-  /* If current mode is VESA_800x600 then save its geometry to restore later */
-  if ((VGLOldMode >= M_VESA_BASE) && (VGLOldMode == M_VESA_800x600)) {
-VGLOldVInfo.size = sizeof(VGLOldVInfo);
-if (ioctl(0, CONS_GETINFO, ))
-  return -1;
-  }
+  /* Save info for old mode to restore font size if old mode is graphics. */
+  VGLOldModeInfo.vi_mode = VGLOldMode;
+  if (ioctl(0, CONS_MODEINFO, ))
+return -1;
+  VGLOldVInfo.size = sizeof(VGLOldVInfo);
+  if (ioctl(0, CONS_GETINFO, ))
+return -1;
 
   VGLDisplay = (VGLBitmap *)malloc(sizeof(VGLBitmap));
   if (VGLDisplay == NULL)


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r345696 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Fri Mar 29 15:57:08 2019
New Revision: 345696
URL: https://svnweb.freebsd.org/changeset/base/345696

Log:
  Fix endless loops for handling SIGBUS and SIGSEGV.
  
  r80270 has the usual wrong fix for unsafe signal handling -- just set
  a flag and return to let an event loop check the flag and do safe
  handling.  This never works for signals like SIGBUS and SIGSEGV that
  repeat and works poorly for others unless the application has an event
  loop designed to support this.
  
  For these signals, clean up unsafely as before, except for arranging that
  nested signals are fatal and forcing a nested signal if the cleanup doesn't
  cause one.

Modified:
  head/lib/libvgl/main.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Fri Mar 29 15:20:48 2019(r345695)
+++ head/lib/libvgl/main.c  Fri Mar 29 15:57:08 2019(r345696)
@@ -31,9 +31,9 @@
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -107,14 +107,22 @@ struct vt_mode smode;
 }
 
 static void 
-VGLAbort(int arg __unused)
+VGLAbort(int arg)
 {
+  sigset_t mask;
+
   VGLAbortPending = 1;
   signal(SIGINT, SIG_IGN);
   signal(SIGTERM, SIG_IGN);
-  signal(SIGSEGV, SIG_IGN);
-  signal(SIGBUS, SIG_IGN);
   signal(SIGUSR2, SIG_IGN);
+  if (arg == SIGBUS || arg == SIGSEGV) {
+signal(arg, SIG_DFL);
+sigemptyset();
+sigaddset(, arg);
+sigprocmask(SIG_UNBLOCK, , NULL);
+VGLEnd();
+kill(getpid(), arg);
+  }
 }
 
 static void


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r345639 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Thu Mar 28 12:28:29 2019
New Revision: 345639
URL: https://svnweb.freebsd.org/changeset/base/345639

Log:
  Fix VGLGetXY(), VGLSetXY() and VGLClear() for MEMBUFs in depths > 8.
  
  This depends on PixelBytes being properly initialized, which it is for
  all bitmaps constructed by libvgl except mouse cursor bitmaps.

Modified:
  head/lib/libvgl/simple.c

Modified: head/lib/libvgl/simple.c
==
--- head/lib/libvgl/simple.cThu Mar 28 10:56:27 2019(r345638)
+++ head/lib/libvgl/simple.cThu Mar 28 12:28:29 2019(r345639)
@@ -102,6 +102,15 @@ VGLSetXY(VGLBitmap *object, int x, int y, u_long color
 !VGLMouseFreeze(x, y, 1, 1, 0x8000 | color)) {
   switch (object->Type) {
   case MEMBUF:
+  switch (object->PixelBytes) {
+  case 2:
+goto vidbuf16;
+  case 3:
+goto vidbuf24;
+  case 4:
+goto vidbuf32;
+  }
+  /* fallthrough */
   case VIDBUF8:
 object->Bitmap[y*object->VXsize+x]=((byte)color);
 break;
@@ -109,8 +118,11 @@ VGLSetXY(VGLBitmap *object, int x, int y, u_long color
object->Bitmap[VGLSetSegment(y*object->VXsize+x)]=((byte)color);
break;
   case VIDBUF16:
+vidbuf16:
   case VIDBUF24:
+vidbuf24:
   case VIDBUF32:
+vidbuf32:
color2mem(color, b, object->PixelBytes);
 bcopy(b, >Bitmap[(y*object->VXsize+x) * object->PixelBytes],
object->PixelBytes);
@@ -156,13 +168,25 @@ __VGLGetXY(VGLBitmap *object, int x, int y)
 
   switch (object->Type) {
 case MEMBUF:
+switch (object->PixelBytes) {
+case 2:
+  goto vidbuf16;
+case 3:
+  goto vidbuf24;
+case 4:
+  goto vidbuf32;
+}
+/* fallthrough */
 case VIDBUF8:
   return object->Bitmap[((y*object->VXsize)+x)];
 case VIDBUF8S:
   return object->Bitmap[VGLSetSegment(y*object->VXsize+x)];
 case VIDBUF16:
+vidbuf16:
 case VIDBUF24:
+vidbuf24:
 case VIDBUF32:
+vidbuf32:
   bcopy(>Bitmap[(y*object->VXsize+x) * object->PixelBytes],
b, object->PixelBytes);
   return (mem2color(b, object->PixelBytes));
@@ -525,6 +549,15 @@ VGLClear(VGLBitmap *object, u_long color)
 VGLMouseFreeze(0, 0, object->Xsize, object->Ysize, color);
   switch (object->Type) {
   case MEMBUF:
+  switch (object->PixelBytes) {
+  case 2:
+goto vidbuf16;
+  case 3:
+goto vidbuf24;
+  case 4:
+goto vidbuf32;
+  }
+  /* fallthrough */
   case VIDBUF8:
 memset(object->Bitmap, (byte)color, object->VXsize*object->VYsize);
 break;
@@ -539,8 +572,11 @@ VGLClear(VGLBitmap *object, u_long color)
 }
 break;
   case VIDBUF16:
+vidbuf16:
   case VIDBUF24:
+vidbuf24:
   case VIDBUF32:
+vidbuf32:
 color2mem(color, b, object->PixelBytes);
 total = object->VXsize*object->VYsize*object->PixelBytes;
 for (i = 0; i < total; i += object->PixelBytes)


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r345637 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Thu Mar 28 09:51:37 2019
New Revision: 345637
URL: https://svnweb.freebsd.org/changeset/base/345637

Log:
  Oops, r345496 got the pointer args backwards for bcopy() in VGLClear for
  segmented modes.
  
  Also fix some style bugs in the 2 changed lines.  libvgl uses a very non-KNF
  style with 2-column indentation with no tabs except for regressions.

Modified:
  head/lib/libvgl/simple.c

Modified: head/lib/libvgl/simple.c
==
--- head/lib/libvgl/simple.cThu Mar 28 09:50:25 2019(r345636)
+++ head/lib/libvgl/simple.cThu Mar 28 09:51:37 2019(r345637)
@@ -556,8 +556,8 @@ VGLClear(VGLBitmap *object, u_long color)
   VGLSetSegment(offset);
   len = min(total - offset, VGLAdpInfo.va_window_size);
   for (i = 0; i < len; i += object->PixelBytes)
-   bcopy(object->Bitmap + (offset + i) % VGLAdpInfo.va_window_size, b,
- object->PixelBytes);
+bcopy(b, object->Bitmap + (offset + i) % VGLAdpInfo.va_window_size,
+  object->PixelBytes);
   offset += len;
 }
 break;


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r345643 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Thu Mar 28 14:21:22 2019
New Revision: 345643
URL: https://svnweb.freebsd.org/changeset/base/345643

Log:
  Fix VGLLine() in depths > 8.
  
  It started truncating its color arg to 8 bits using plot() in r229415.
  The version in r229415 is also more than 3 times slower in segmented
  modes, by doing more syscalls to move the window.

Modified:
  head/lib/libvgl/simple.c

Modified: head/lib/libvgl/simple.c
==
--- head/lib/libvgl/simple.cThu Mar 28 13:44:18 2019(r345642)
+++ head/lib/libvgl/simple.cThu Mar 28 14:21:22 2019(r345643)
@@ -248,7 +248,7 @@ VGLGetXY(VGLBitmap *object, int x, int y)
 #define SL_ABSOLUTE(i,j,k) ( (i-j)*(k = ( (i-j)<0 ? -1 : 1)))
 
 void
-plot(VGLBitmap * object, int x, int y, int flag, byte color)
+plot(VGLBitmap * object, int x, int y, int flag, u_long color)
 {
   /* non-zero flag indicates the pixels need swapping back. */
   if (flag)


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r345585 - head/lib/libvgl

2019-09-03 Thread Bruce Evans
Author: bde
Date: Wed Mar 27 18:03:34 2019
New Revision: 345585
URL: https://svnweb.freebsd.org/changeset/base/345585

Log:
  Fix accessing pixels under the mouse cursor:
  
  Reading of single pixels didn't look under the cursor.
  
  Copying of 1x1 bitmaps didn't look under the cursor for either reading
  or writing.
  
  Copying of larger bitmaps looked under the cursor for at most the
  destination.
  
  Copying of larger bitmaps looked under a garbage cursor (for the Display
  bitmap) when the destination is a MEMBUF.  The results are not used, so
  this only wasted time and flickered the cursor.
  
  Writing of single pixels looked under a garbage cursor for MEMBUF
  destinations, as above except this clobbered the current cursor and
  didn't update the MEMBUF.  Writing of single pixels is not implemented
  yet in depths > 8.  Otherwise, writing of single pixels worked.  It was
  the only working case for accessing pixels under the cursor.
  
  Clearing of MEMBUFs wasted time freezing the cursor in the Display bitmap.
  
  The fixes abuse the top bits in the color arg to the cursor freezing
  function to control the function.  Also clear the top 8 bits so that
  applications can't clobber the control bits or create 256 aliases for
  every 24-bit pixel value in depth 32.
  
  Races fixed:
  
  Showing and hiding the cursor only tried to avoid races with the mouse
  event signal handler for internal operations.  There are still many
  shorter races from not using volatile or sig_atomic_t for the variable
  to control this.  This variable also controls freezes, and has more
  complicated states than before.
  
  The internal operation of unfreezing the cursor opened a race window
  by unsetting the signal/freeze variable before showing the cursor.

Modified:
  head/lib/libvgl/bitmap.c
  head/lib/libvgl/mouse.c
  head/lib/libvgl/simple.c

Modified: head/lib/libvgl/bitmap.c
==
--- head/lib/libvgl/bitmap.cWed Mar 27 17:55:39 2019(r345584)
+++ head/lib/libvgl/bitmap.cWed Mar 27 18:03:34 2019(r345585)
@@ -361,9 +361,13 @@ VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
 {
   int error;
 
-  VGLMouseFreeze(dstx, dsty, width, hight, 0);
+  if (src->Type != MEMBUF)
+VGLMouseFreeze(srcx, srcy, width, hight, 0);
+  if (dst->Type != MEMBUF)
+VGLMouseFreeze(dstx, dsty, width, hight, 0);
   error = __VGLBitmapCopy(src, srcx, srcy, dst, dstx, dsty, width, hight);
-  VGLMouseUnFreeze();
+  if (src->Type != MEMBUF || dst->Type != MEMBUF)
+VGLMouseUnFreeze();
   return error;
 }
 

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Wed Mar 27 17:55:39 2019(r345584)
+++ head/lib/libvgl/mouse.c Wed Mar 27 18:03:34 2019(r345585)
@@ -102,6 +102,7 @@ VGLMousePointerShow()
   int i, pos, pos1;
 
   if (!VGLMouseVisible) {
+VGLMouseFrozen++;
 VGLMouseVisible = 1;
 crtcidx = inb(0x3c4);
 crtcval = inb(0x3c5);
@@ -124,6 +125,7 @@ VGLMousePointerShow()
 outb(0x3c5, crtcval);
 outb(0x3ce, gdcidx);
 outb(0x3cf, gdcval);
+VGLMouseFrozen--;
   }
 }
 
@@ -133,6 +135,7 @@ VGLMousePointerHide()
   byte crtcidx, crtcval, gdcidx, gdcval;
 
   if (VGLMouseVisible) {
+VGLMouseFrozen++;
 VGLMouseVisible = 0;
 crtcidx = inb(0x3c4);
 crtcval = inb(0x3c5);
@@ -144,6 +147,7 @@ VGLMousePointerHide()
 outb(0x3c5, crtcval);
 outb(0x3ce, gdcidx);
 outb(0x3cf, gdcval);
+VGLMouseFrozen--;
   }
 }
 
@@ -170,7 +174,7 @@ VGLMouseAction(int dummy)   
   struct mouse_info mouseinfo;
 
   if (VGLMouseFrozen) {
-VGLMouseFrozen++;
+VGLMouseFrozen += 8;
 return;
   }
   mouseinfo.operation = MOUSE_GETINFO;
@@ -257,9 +261,8 @@ VGLMouseFreeze(int x, int y, int width, int hight, u_l
 {
   int i, xstride, ystride;
 
-  if (!VGLMouseFrozen) {
-VGLMouseFrozen = 1;
-if (width > 1 || hight > 1) {  /* bitmap */
+VGLMouseFrozen++;
+if (width > 1 || hight > 1 || (color & 0xc000) == 0) { /* bitmap */
   if (VGLMouseShown == 1) {
 int overlap;
 
@@ -283,29 +286,38 @@ VGLMouseFreeze(int x, int y, int width, int hight, u_l
   y >= VGLMouseYpos && y < VGLMouseYpos + MOUSE_IMG_SIZE) {
 xstride = VGLDisplay->PixelBytes;
 ystride = MOUSE_IMG_SIZE * xstride;
-for (i = 0; i < xstride; i++, color >>= 8)
-  VGLMouseSave.Bitmap[(y-VGLMouseYpos)*ystride+
-  (x-VGLMouseXpos)*xstride+i] = color;
-if (VGLMouseAndMask->Bitmap 
-  [(y-VGLMouseYpos)*MOUSE_IMG_SIZE+(x-VGLMouseXpos)]) {
-  return 1;
+if (color & 0x4000) {  /* Get */
+  color = 0;
+  for (i = xstride - 1; i >= 0; i--)
+color = (color << 8) |
+VGLMouseSave.Bitmap[(y-VGLMouseYpos)*ystride+
+

Re: svn commit: r351319 - in head/usr.sbin/makefs: ffs msdos

2019-08-29 Thread Bruce Evans

On Wed, 21 Aug 2019, Ed Maste wrote:


Author: emaste
Date: Wed Aug 21 01:45:29 2019
New Revision: 351319
URL: https://svnweb.freebsd.org/changeset/base/351319

Log:
 makefs: use `char *` not `void *` for buf b_data, drop casts in msdos

 (The kernel uses caddr_t.)


This is much better than churning the copy of the working code.

However, the kernel type is still bogus.  caddr_t should not exist, and
should have been more like vm_offset_t to begin with.  void * is no good
as an opaque type for it, since void * is only good for C addresses within
a single address space, but caddr_t is supposed to be able to represent
anything in a (possibly multiple) "core" address space.  [u]intptr_t has
the same problem.  Bus space addresses are also withing a single address
space and in general need a tag for uniqueness.

caddr_t has been char * for too long, so too much code including buf b_data
depends on it being precisely char * or u_char * to work.  char * is an
honestly broken variant of void *.  It is similarly limited to a single
address space.  This is hard to fix.  It works for [Free]BSD since no arches
with more than a single address space are supported (i386 with PAE or
pae_mode=1 or pae_mode has a larger physical address space where addresses
aren't unique, but only the kernel can see this).

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r350713 - head/sys/kern

2019-08-08 Thread Bruce Evans

On Thu, 8 Aug 2019, Conrad Meyer wrote:


Log:
 ddb(4): Add 'sysctl' command

 Implement `sysctl` in `ddb` by overriding `SYSCTL_OUT`.  When handling the
 req, we install custom ddb in/out handlers.  The out handler prints straight
 to the debugger, while the in handler ignores all input.  This is intended
 to allow us to print just about any sysctl.

 There is a known issue when used from ddb(4) entered via 'sysctl
 debug.kdb.enter=1'.  The DDB mode does not quite prevent all lock
 interactions, and it is possible for the recursive Giant lock to be unlocked
 when the ddb(4) 'sysctl' command is used.  This may result in a panic on
 return from ddb(4) via 'c' (continue).  Obviously, this is not a problem
 when debugging already-paniced systems.


Locking for kdb was grossly broken in r339917, by setting and unsetting
the SCHEDULER_STOPPED() flag on entry and exit to kdb.  This flag is only
usable during panic() since when it is set all mutex operations potentially
corrupt their mutex, and unsetting the flag doesn't undo the corruption.

Many different types of corruption are possible, but my simplest example
if like the one here for Giant, but for a spinlock.  kdb runs happily while
SCHEDULER_STOPPED() is set, but if it corrupts a mutex then the corruption
is fatal later when SCHEDULER_STOPPED() is clear (setting SCHEDULER_STOPPED()
breaks early detection of the corruption in most cases).

kern_sysctl.c does only 1 pair of mutex calls.  In
sysctl_root_handle_locked(), it locks and unlocks Giant for the !MPSAFE case.
If that is the only mutex call, then the problem is easy to fix by not
making these calls if kdb_active.

One of my versions of kdb asserts that no mutex calls are made if
kdb_active.  This makes it easy to find buggy mutex calls.
Unfortunately, low-quality low level console drivers like vt make such
calls unconditionally.  I used this to avoid all the buggy calls in
syscons (a typical error there was for to wander into wakeup or timeout
code which uses mutexes.  This was "fixed" by removing things like
beeping for errors.  The keyboard driver uses Giant fundamentally.
This was "fixed" using the usual hack of not doing the mutex call if
kdb_active).


...
Modified: head/sys/kern/kern_sysctl.c
==
--- head/sys/kern/kern_sysctl.c Thu Aug  8 00:33:23 2019(r350712)
+++ head/sys/kern/kern_sysctl.c Thu Aug  8 00:42:29 2019(r350713)
...
+/*
+ * Run a sysctl handler with the DDB oldfunc and newfunc attached.
+ * Instead of copying any output to a buffer we'll dump it right to
+ * the console.
+ */
+static int
+db_sysctl(struct sysctl_oid *oidp, int *name, u_int namelen,
+void *old, size_t *oldlenp, size_t *retval, int flags)
+{
+   struct sysctl_req req;
+   int error;
+
+   /* Setup the request */
+   bzero(, sizeof req);
+   req.td = kdb_thread;
+   req.oldfunc = sysctl_old_ddb;
+   req.newfunc = sysctl_new_ddb;
+   req.lock = REQ_UNWIRED;
+   if (oldlenp) {
+   req.oldlen = *oldlenp;
+   }
+   req.validlen = req.oldlen;
+   if (old) {
+   req.oldptr = old;
+   }
+
+   /* Setup our globals for sysctl_old_ddb */
+   g_ddb_oid = oidp;
+   g_ddb_sysctl_flags = flags;
+   g_ddb_sysctl_printed = 0;


This has many style bugs.  So does the rest of the file.


+
+   error = sysctl_root(0, name, namelen, );


This makes invalid mutex calls for all !MPSAFE sysctls.

Setting SCHEDULER_STOPPED() for kdb is only very broken for spin mutexes.
Then for a contested mutex, mtx_lock_spin() ends up doing nothing except
invalid lock and/or kdtrace profiling when it finds SCHEDULER_STOPPED()
set. but mtx_unlock_spin() never checks SCHEDULER_STOPPED(), so it ends
up corrupting the mutex and the spinlock state by attempting to unlock
a mutex whose corresponding locking was not done.  INVARIANTS causes
similar bugs for recursed-on spin mutexes.  Without INVARIANTS, everything
is done inline without checking SCHEDULER_STOPPED(), so it works well enough
in practice in uncontested non-recursive cases.  With INVARIANTS, the null
locking gives no increment of the recursion counter and no call to
spinlock_enter(), but the non-null unlocking decrements the recursion
counter and calls spinlock_exit().

For sleep mutexes, unlocking checks SCHEDULER_STOPPED() consistently with
locking, so the bugs are smaller.  The easiest way to demonstrate them is
to configure INVARIANTS and WITNESS.  Starting with Giant unheld,
mtx_lock() does nothing with the mutex except invalid lock and/or
kdtrace profiling.  mtx_unlock) calls __mtx_unlock_flags()
which calls __mtx_assert(m, MA_OWNED), but this check is subverted by not
doing it when SCHEDULER_STOPPED().  But before that, __mtx_unlock_flags()
calls WITNESS_UNLOCK() and witness_unlock() is not similarly subverted.
Also, WITNESS uses a critical spin mutex w_mtx, and this is corrupted as
above.

Bruce

Re: svn commit: r350532 - head/sys/netinet6

2019-08-02 Thread Bruce Evans

On Fri, 2 Aug 2019, Bjoern A. Zeeb wrote:


Log:
 frag6.c: sort includes

 Sort includes and remove duplicate kernel.h as well as the unneeded
 systm.h.


sys/systm.h is always needed, since it defines macros and functions which
might be needed in other headers.  frag6.c even uses KASSERT() directly.


Modified: head/sys/netinet6/frag6.c
==
--- head/sys/netinet6/frag6.c   Fri Aug  2 07:41:36 2019(r350531)
+++ head/sys/netinet6/frag6.c   Fri Aug  2 10:06:54 2019(r350532)
@@ -37,18 +37,16 @@ __FBSDID("$FreeBSD$");
#include "opt_rss.h"

#include 
-#include 


This was correct.  sys/systm.h must also be included in this order.

Now the KASSERT() used in frag6.c is apparently obtained via pollution
in some other header.


-#include 
-#include 
-#include 
#include 
+#include 


sys/errno is standard pollution in sys/param.h (if _KERNEL).  It is a style
bug to not depend on this.


#include 
+#include 
#include 
+#include 


sys/malloc.h is polluted by including sys/systm.h.


+#include 


sys/mbuf.h is polluted by including sys/systm.h.


#include 
#include 
-#include 
#include 


sys/time.h is standard pollution in sys/param.h (if _KERNEL).  It is a style
bug to not depend on this.


-#include 
#include 

#include 


machine/atomic.h is standard non-pollution on sys/systm.h.  It is a style
bug to include it directly.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r350179 - head/lib/libutil

2019-07-20 Thread Bruce Evans

On Sat, 20 Jul 2019, John Baldwin wrote:


Log:
 expand_number(3) parses suffixes, not prefixes.


This is not quite correct, although conflating prefixes and suffixes is
one of the bugs that I pointed out in mails about [de]humanize_number and
expand_number() long ago.

Bugs in expand_number() start with its name.  It doesn't expand numbers.
It parses strings and produces integers with a wrong limited type/range
(uint64_t instead of uintmax_t plus sign info).  I don't know what it
means to expand a number, but this is close to the opposite.

expand_number() is not nearly as badly designed as humanize_number().
humanize_number() doesn't humanize numbers.  It converts integers with
a different wrong limited type/range (int64_t instead of uint64_t plus
sign info) to a hideous/dehumanized string format.  The humanized format
would be decimal decimal.  humanize_number() produces a scientific format.

humanize_number() still documents SI prefixes, and has a suffix arg which
gives the units.  Its SI prefixes are prefixes to the suffix.  E.g., a
prefix of "K" and a suffix of "B" gives units of non-disk-marketers
kilobytes.  It is only when the suffix is null that the prefix becomes
a suffix.  Most quantities have units, but it is common to omit the units
in the string representation to save space.  expand_number() doesn't even
support units, except it treats the suffix "B" or "b" as a null unit
provided it doesn't have a prefix (e.g., "1B" gives 1, byut "1KB" is a 
syntax error).


strtonum() uses the long long abomination instead of the correct type
(uintmax_t with sign info).  Its name is better, but uses the precious
str* namespace for a badly designed API.

I would prefer a strtonum() that is more like expand_number() (not too
much error handling) but handles any number of suffixes and multipliers
like the number-parsing function in dd.  This should be almost as easy
to use as atoi(), but have some error handling.  E.g.,

uintmax_t strtonum(const char *nptr, const char *errspec, ...);

where simple uses use errspec = NULL to get default error handling
similar to expand_number().  errspec would need 3 specifiers to specify
the last 3 args in the current strtonum().


Modified: head/lib/libutil/expand_number.3
==
--- head/lib/libutil/expand_number.3Sat Jul 20 15:59:49 2019
(r350178)
+++ head/lib/libutil/expand_number.3Sat Jul 20 16:03:54 2019
(r350179)
@@ -42,11 +42,10 @@
.Sh DESCRIPTION
The
.Fn expand_number
-function unformats the
+function parses the


Better.

The supported formats are still undocumented.  Not even that they are
integers.  They may have leading whitespace and signs, or hex and octal
prefixes (anything parseable by strtoumax(), with special treatment of
a single optional suffix character).


.Fa buf
-string and stores a unsigned 64-bit quantity at address pointed out by the
-.Fa num
-argument.
+string and stores a unsigned 64-bit quantity at
+.Fa *num .


"unsigned 64-bit quantity" is a bad way of spelling of "uint64_t".
uint64_t's aren't quantities.


.Pp
The
.Fn expand_number
@@ -54,9 +53,9 @@ function
is case-insensitive and
follows the SI power of two convention.


There is no SI power of 2 convention according to Wikipedia.

humanize_number() and its bugs must be understood to see what this means.

Google gives approximately zero hits for "SI suffix".  It automatically
translates "SI suffix" to "SI prefix" and of course finds zillions of hits
for that.  humanize_number(3) says that it "follows the traditional
computer science conventions by default, rather than the IEE/IEC (and now
also SI) power of two convention...", but according to Wikipedia, IEC
60027-2 Amendment 2 confirms that SI only supports power of 10 prefixes.

According to Wikipedia, the power of 2 convention is IEC for kibi
through yobi, and JEDEC has the better traditional prefixes and names for
K/kilo though G/Giga.

k is documented to mean 1000 and K 1024 for humanize_number(), but
expand_number() treats both as 1024.  The other prefixes can't be
disambiguated like this.


.Pp
-The prefixes are:
-.Bl -column "Prefix" "Description" "100" -offset indent
-.It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier"
+The suffixes are:
+.Bl -column "Suffix" "Description" "100" -offset indent
+.It Sy "Suffix" Ta Sy "Description" Ta Sy "Multiplier"
.It Li K Ta No kilo Ta 1024
.It Li M Ta No mega Ta 1048576
.It Li G Ta No giga Ta 1073741824
@@ -74,7 +73,7 @@ function will fail if:
.It Bq Er EINVAL
The given string contains no digits.
.It Bq Er EINVAL
-An unrecognized prefix was given.
+An unrecognized suffix was given.
.It Bq Er ERANGE
Result doesn't fit into 64 bits.
.El


Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r349391 - head/sys/kern

2019-07-17 Thread Bruce Evans

On Tue, 16 Jul 2019, Alan Somers wrote:


On Tue, Jul 16, 2019 at 3:48 AM Bruce Evans  wrote:


On Mon, 15 Jul 2019, John Baldwin wrote:

...
I'm not sure which variants are most readable:

...

C)
   if (fp->f_seqcount + howmany(resid, 16384) < fp->f_seqcount)
   fp->f_seqcount = IO_SEQMAX;
   else
   fp->f_seqcount = lmin(IO_SEQMAX,
   fp->f_seqcount + howmany(resid, 16384));

I'm probably not a fan of C).


On supported arches, it recovers from overflow in howmany(), but only if
the compiler doesn't optimize away the recovery.

The first part can be done better:

if (uio->uio_resid >= IO_SEQMAX * 16384)
fp->f_seqcount = IO_SEQMAX;

Then for the second part, any version works since all values are small and
non-negative, but I prefer to restore the the version that I rewrote 15-20
years ago and committed 11 years ago (r175106):

fp->f_seqcount += howmany(uio->uio_resid, 16384);
if (fp->f_seqcount > IO_SEQMAX)
fp->f_seqcount = IO_SEQMAX;
...

Bruce,
   Is this how you want it?
Index: sys/kern/vfs_vnops.c
===
--- sys/kern/vfs_vnops.c(revision 349977)
+++ sys/kern/vfs_vnops.c(working copy)
@@ -499,8 +499,13 @@
 * closely related to the best I/O size for real disks than
 * to any block size used by software.
 */
-fp->f_seqcount += lmin(IO_SEQMAX,
-howmany(uio->uio_resid, 16384));
+if (uio->uio_resid >= IO_SEQMAX * 16384)
+fp->f_seqcount = IO_SEQMAX;
+else {
+fp->f_seqcount += howmany(uio->uio_resid, 16384);
+if (fp->f_seqcount > IO_SEQMAX)
+fp->f_seqcount = IO_SEQMAX;
+}
return (fp->f_seqcount << IO_SEQSHIFT);
}


That looks OK, except it is misformatted with tabs corrupted to other than
8 spaces.

I checked that uio_resid is checked by some callers to be >= 0, so we
don't have to check that here.  (Callers between userland and here
start with size_t nbytes or an array of sizes for readv(), and have
to check that nbytes or the sum of the sizes fits in ssize_t, else
overflow would alread have occurred on assigment to uio_resid.  Callers
that construct a uio that is not so directly controlled by userland
presumably don't construct ones with unusable sizes.)

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r349391 - head/sys/kern

2019-07-16 Thread Bruce Evans

On Mon, 15 Jul 2019, John Baldwin wrote:


On 7/14/19 12:08 PM, Conrad Meyer wrote:


This change restores the possible overflow beyond IO_SEQMAX that the
removed conditional prevented.

On Tue, Jun 25, 2019 at 12:44 PM Alan Somers  wrote:


I thought the same for a while on Tue, Jan 25, then didn't reply since I
saw a non-problem while writing the reply.  Actually, all versions are
broken.


Author: asomers
Date: Tue Jun 25 19:44:22 2019
New Revision: 349391
URL: https://svnweb.freebsd.org/changeset/base/349391

--- head/sys/kern/vfs_vnops.c   Tue Jun 25 19:36:01 2019(r349390)
+++ head/sys/kern/vfs_vnops.c   Tue Jun 25 19:44:22 2019(r349391)
@@ -499,10 +499,8 @@ sequential_heuristic(struct uio *uio, struct file *fp)
 * closely related to the best I/O size for real disks than
 * to any block size used by software.
 */
-   fp->f_seqcount += MIN(IO_SEQMAX,
+   fp->f_seqcount += lmin(IO_SEQMAX,
howmany(uio->uio_resid, 16384));
-   if (fp->f_seqcount > IO_SEQMAX)
-   fp->f_seqcount = IO_SEQMAX;
return (fp->f_seqcount << IO_SEQSHIFT);
}


Overflow occurs in all versions in howmany() when uio_resid is near
its limit of SSIZE_MAX.  Then adding (65536 - 1) to uio_resid overflows.
The behaviour is undefined, but usually the addition gives a large
negative value and howmany gives a not so large negative value after
dividing by 65536.

In the previous version, MIN() preserves signedness and the type of
howmany(), which is always long (since ssize_t happens to be long on all
supported arches).  The large negative value is less than IO_SEQMAX sinc
that has a correct type (signed int) and is non-negative.  So MIN() preserves
the large negative value.  This is blindly added to f_seqcount, giving
another overflow on 64-bit arches and a garbage negative value on 32-bit
arches if f_seqcount was not garbage.  The removed conditional only fixes
up large positive values, so has no effect in this case.  Finally, left
shifting the garbage gives further undefined behaviour.

The second overflow on 64-bit arches is because the not so large negative
value is still much larger than can be represented in f_seqcount.
Values near -SSIZE_MAX have 63 value bits, so dividing by 16384 leaves
47 value bits, but f_seqcount has only 31 value bits.

In this version, lmin() happens to give the same result as MIN() on all
supported machines, because ssize_t happens to have the same representation
on all supported machines.  So overflows occur as before for large uio_resid.

So this change makes no differences for the 2 overflows for uio_resid near
SSIZE_MAX.  But removing the conditional restores an overflow that actually
was fixed in a previous recent commit.


Perhaps instead this should be:

fp->f_seqcount = lmin(IO_SEQMAX,
  fp->f_seqcount + howmany(...));


This works to restore the check in the removed conditional, but is a bit
subtle and leaves the 2 old overflow bugs unfixed.


While I agree with your assessment of the removed conditional, I think the
suggestion above can have a funky overflow where f_seqcount + howmany(...) ends
up less than IO_SEQMAX and this expression would then be used instead of 
IO_SEQMAX?


This only happens when howmany() itself overflows.  Otherwise, dividing by
16384 reduces the value enough to add f_seqcount to howmany(...) without
overflow.


The first lmin seems designed to minimize what we add in the hope that since the
existing value is bounded to '0...IO_SEQMAX' the result of the += can only be in
the range '0...2*IO_SEQMAX'.


One addition doesn't overflow, and the shift could be clamped later, but
overflow still occurs after approx. INT_MAX / IO_SEQMAX additions, so it
is better to clamp earlier.


I'm not sure which variants are most readable:

A)
   fp->f_seqcount += lmin(IO_SEQMAX,
   howmany(resid, 16384));
   if (fp->f_seqcount > IO_SEQMAX)
   fp->f_seqcount = IO_SEQMAX;


This change is because I said that using the unsafe macro MIN() is a style
bug.  I also said that using the lmin() family is too hard, since it is
not type generic.  I didn't notice the overflow problem in howmany().

This has another style bug -- using lmin() and then open-coding the clamp
f->f_seqcount = imax(f->f_seqcount, IO_SEQMAX).  This is sort of backwards --
we use open code for the simple case because it is simple with either
spelling, but we use lmin() for the complicated case to avoid spelling out
the howmany() expression twice.  This obscures the 2 overflow bugs in the
howmany() expression and many delicate type promotions and type equivalences
that are needed for lmin() to work.


B)
   fp->f_seqcount += lmin(IO_SEQMAX,
   howmany(resid, 16384));
   fp->f_seqcount = lmin(fp->f_seqcount, IO_SEQMAX);


Consistent style, but another has another type error.  f_seqcount has type
int.  Of course, lmin() handles ints too, but to see that it 

Re: svn commit: r349989 - head/sys/kern

2019-07-15 Thread Bruce Evans

On Sun, 14 Jul 2019, Michael Tuexen wrote:


Log:
 Improve the input validation for l_linger.
 When using the SOL_SOCKET level socket option SO_LINGER, the structure
 struct linger is used as the option value. The component l_linger is of
 type int, but internally copied to the field so_linger of the structure
 struct socket. The type of so_linger is short, but it is assumed to be
 non-negative and the value is used to compute ticks to be stored in a
 variable of type int.

 Therefore, perform input validation on l_linger similar to the one
 performed by NetBSD and OpenBSD.


This still overflows, at least in FreeBSD.  FreeBSD really does have type
short (or int16_t in the user struct) for l_linger, so overflow now occurs
when SHRT_MAX < l.linger <= USHRT_MAX.  The overflow is to a negative value
on all supported arches.


 Thanks to syzkaller for making me aware of this issue.

 Thanks to markj@ for pointing out that a similar check should be added
 to so_linger_set().


This check seems to be wrong, but it is hard to be sure since
so_linger_set() is never referenced.  Using KASSERT() is wrong unless
the caller is supposed to have checked the args and usually unnecessary
if the caller has checked the args.


Modified: head/sys/kern/uipc_socket.c
==
--- head/sys/kern/uipc_socket.c Sun Jul 14 21:08:54 2019(r349988)
+++ head/sys/kern/uipc_socket.c Sun Jul 14 21:44:18 2019(r349989)
@@ -2776,7 +2776,12 @@ sosetopt(struct socket *so, struct sockopt *sopt)
error = sooptcopyin(sopt, , sizeof l, sizeof l);
if (error)
goto bad;
-


This fixes a style bug (extra blank line separating related code).


+   if (l.l_linger < 0 ||
+   l.l_linger > USHRT_MAX ||


This adds a style bug (excessive line splitting) together with the wrong
limit.

The correct limit is INT16_MAX since the user struct uses int16_t and we
don't want to allow that to overflow.  SHRT_MAX is only the same as
INT16_MAX on all supported arches.


+   l.l_linger > (INT_MAX / hz)) {


This adds a syle bug (excessive parentheses).  It is unfortunately technically
necessary for a paranoid check.  We blindly multiply by hz later and want to
ensure no overflow then.  Overflow is barely possible with the correct limit
of 32767.  Then overflow on multiplication by hz would occur with maximal
l_linger and 32-bit ints when hz = 65536.  hz = 65536 is barely reasonable.


+   error = EDOM;
+   goto bad;
+   }
SOCK_LOCK(so);
so->so_linger = l.l_linger;
if (l.l_onoff)
@@ -4105,6 +4110,9 @@ so_linger_get(const struct socket *so)
void
so_linger_set(struct socket *so, int val)
{
+
+   KASSERT(val >= 0 && val <= USHRT_MAX && val <= (INT_MAX / hz),
+   ("%s: val %d out of range", __func__, val));

so->so_linger = val;
}


Unreached code with the same error in the limit and the excessive
parentheses, but otherwise fewer style bugs.

r180641 in 2008 added mounds of accessor functions like this.  Using
these is painful compared with direct acccess, and there is currently
1 whole use of so_{state,options,error,linger,protosw}_{set,get} in
the sys tree.  This is a so_options_get() in cxgbe.  cxgbe elsewhere
uses 3 direct accesses to so->so_options alone, including 1 '|='
operation which would be especially painful using 2 accessor functions.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r349896 - head/contrib/telnet/telnet

2019-07-11 Thread Bruce Evans

On Thu, 11 Jul 2019, Enji Cooper wrote:


On Jul 10, 2019, at 3:36 PM, Philip Paeps  wrote:

Author: philip
Date: Wed Jul 10 22:36:14 2019
New Revision: 349896
URL: https://svnweb.freebsd.org/changeset/base/349896

Log:
 telnet: fix minor style violation

 While here also fix a very unlikely NULL pointer dereference.


I see no fix here.


Modified: head/contrib/telnet/telnet/commands.c
==
--- head/contrib/telnet/telnet/commands.c   Wed Jul 10 22:23:59 2019
(r349895)
+++ head/contrib/telnet/telnet/commands.c   Wed Jul 10 22:36:14 2019
(r349896)
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include 
#include 

+#include 
#include 
#include 
#include 
@@ -1654,11 +1655,13 @@ env_init(void)
|| (strncmp((char *)ep->value, "unix:", 5) == 0))) {
char hbuf[256+1];
char *cp2 = strchr((char *)ep->value, ':');
+size_t buflen;


This adds a different type of style bug (indentation via spaces instead of
tabs).



gethostname(hbuf, sizeof(hbuf));
hbuf[sizeof(hbuf)-1] = '\0';
-unsigned int buflen = strlen(hbuf) + strlen(cp2) + 1;
+   buflen = strlen(hbuf) + strlen(cp2) + 1;
cp = (char *)malloc(sizeof(char)*buflen);
+   assert(cp != NULL);


This will unfortunately still segfault if assert is compiled out of the system 
as a no-op (-DNDEBUG).


telnet is unlikely to be compiled with -DNDEBUG, since it didn't use assert()
before and this commit doesn't change its Makefile to control its new use
of assert().

Any it doesn't fix the error either.  On must arches, it turns a nice
restartable null pointer trap into an unrestartable abort().  The program
crashes in both cases.


I genuinely think using asprintf instead is the way to go, as Eitan and Warner 
brought up, since it reduces complexity in the program.


asprintf() is only slightly easier to use.  You still have to check if it
succeeded, and free the storage that it allocates.  It increases the
complexity of the program compared with static allocation and strcat().

Example of a simple method:

char buf[MAXHOSTNAMELEN + 256];
...

cp2 = ...;
/*
 * Must bound cp2's length if we are paranoid, since cp2
 * is in the environment.  Use 256 for the bound, for
 * simple portable allocation above (don't use unportable
 * alloca() or newfangled VLAs to try to support much
 * larger sizes.  Since we are paranoid, we are reluctant
 * to even allocate 1-byte buffers as local variables.
 */
if (strlen(cp2) > 256)
abort();/* sloppy, like assert() ... */

/*
 * Although MAXHOSTNAMELEN is undocumented, we assume that
 * it equals the documented {HOST_NAME_MAX} + 1 elsewhere
 * so may as well assume this here.  We trust gethostname()
 * to work as documented and nul-terminate what it returns
 * provided it succeeds and the buffer is large enough.
 */
if (gethostname(buf, MAXHOSTNAMELEN) != 0)
abort();/* sloppy, but better than nothing */

#ifdef TRUE_PARANOID
buf[MAXHOSTNAMELEN] = '\0';
assert(strlen(buf) < MAXHOSTNAMELEN);
#endif

/* The buffer is large enough, by construction. */
strcat(buf, cp2);

The above is much more readable without any comments or error checking.  I
can't quite make it fail nicely with null pointer traps then:

buf = alloca(MAXHOSTNAMELEN + strlen(cp2));
gethostname(buf, MAXHOSTNAMELEN);
strcat(buf, cp2);

Using alloca() is better than a VLA, since it its possible in principle for
it to fail and return a null pointer giving a nice trap.

Using asprintf():

/* Minor unportabilities, as above: */
char hbuf[MAXHOSTNAMELEN];

/*
 * Only needs error checking if TRUE_PARANOID, as above
 * (might be better to order the initialization so as to
 * use out global hostname variable):
 */
gethostname(hbuf, MAXHOSTNAMELEN);

/* Remove cp2 above; expression for cp2 moved here: */
asprintf(, "%s%s", buf, strchr((char *)ep->value, ':'));
if (buf == NULL)
abort();/* sloppy, like assert() ... */
...
free(buf);  /* more messes to free it */

xasprintfa() (asprintf() to an alloca()ed buffer with internal abort() of
the allocation is impossible) would be most convenient here.

Bruce

Re: svn commit: r349890 - head/contrib/telnet/telnet

2019-07-11 Thread Bruce Evans

On Thu, 11 Jul 2019, Alexey Dokuchaev wrote:


On Wed, Jul 10, 2019 at 05:42:04PM +, Philip Paeps wrote:

New Revision: 349890
URL: https://svnweb.freebsd.org/changeset/base/349890

Log:
  telnet: fix a couple of snprintf() buffer overflows


I see few fixes in this fix.  I see even more style bugs than before.


Modified: head/contrib/telnet/telnet/commands.c
@@ -1655,10 +1655,11 @@ env_init(void)
char hbuf[256+1];
char *cp2 = strchr((char *)ep->value, ':');

-   gethostname(hbuf, 256);
-   hbuf[256] = '\0';
-   cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
-   sprintf((char *)cp, "%s%s", hbuf, cp2);


Would it make sense to add something like __attribute__ ((deprecated))
to those unsafe functions like gets(), sprintf(), etc.?  Or it would
cause too much PITA?


sprintf() is safe to use and was used perfectly correctly (except for not
not checking the validity of most of its args: no check of the result of
gethostname() or malloc(), and no check for overflow in
'strlen(hbuf) + strlen(cp2) + 1'.  malloc() is used to provide a buffer
just large enough for sprintf() to not overflow the buffer, modulo the
missing error checking.  Blindly changing to snprintf() does little
to improve this.  It gives a garbage buffer instead of buffer overrun
in some of the error cases.  It is missing error checking.

The bugs visible in the above are:
- hard-coded size for hbuf.  The correct size is {HOST_NAME_MAX} + 1.
  HOST_NAME_MAX is intentionally not defined in FreeBSD's , so
  even unportable POSIX applications have to deal with the full complexity
  of POSIX limits (they can't simply hard-code HOST_NAME_MAX).  POSIX
  requires using sysconf(_SC_HOST_NAME_MAX) and dealing with errors and
  indeterminate values reported by it.  Unfortunately, FreeBSD also has
  MAXHOSTNAMELEN.  sysconf(_SC_HOST_NAME_MAX) just returns this minus 1.
  This is is 256.  The hard-coded 256 in the above is essentially this,
  and adding 1 to this is nonsense.

  telnet uses MAXHOSTNAMELEN for global variables.  It also #defines
  MAXHOSTNAMELEN as 256 if it is not defined in an included header.  So
  if the extra 1 were actually used, then the global variables couldn't
  hold hostnames and there would be bugs elswhere.

  Honestly unportable code would use MAXHOSTNAME everywhere, and not add
  1 to it, and depend on this being large enough.  gethostname() guarantees
  to nul-terminated if it succeeds and the buffer is large enough.

  telnet uses gethostname() in 1 other place.  In telnet.c, it initializes
  the global local_host which has size MAXHOSTNAME.  Of course it doesn't
  check for errors.  It does force nul-termination.

- missing spaces around binary operator in '256+1'

- initialization in declaration of cp2

- bogus cast to char * in declaration of cp2.  This breaks the warning that
  ep->value has the bogus type unsigned char *.  Not many character arrays
  actually need to have type unsigned char *, and if they do then it might
  be an error to pass them to str*() functions since str*() functions are
  only guaranteed to work right for plain char *.

- no error check for gethostname(), bogus dishonestly unportable size for
  hbuf, and partial fixup for these bugs by forcing nul-termination (see above)

- bogus cast of malloc() to char *.  This was more needed 30-40 years ago
  for bad code that doesn't declare malloc() in a standard header or doesn't
  include that header.  Telnet is that old, so this wasn't bogus originally.

- no check for overflow in 'strlen(hbuf) + strlen(cp2) + 1'.  Checking this
  would be silly, but not much sillier than forcing nul-termination after
  not trusting gethostname() and/or our buffer size.  strlen(hbuf) is known
  to be small, and strlen(cp2) must be known to be non-preposterous, else
  overflow is possible.  However, cp2 is a substring of an environment
  variable, so it can be almost as large as the address space if a malicious
  environment can be created.  Perhaps it is limited to ARG_MAX.  Practical
  code could limit its size to 256 or so and statically allocate the whole
  buffer on the stack.  Or don't limit it, and use alloca() or a VLA to
  allocate the whole buffer on the stack.  Paranoid code of course can't
  even have a stack, unless the C runtime checks for stack overflow and
  the program can handle exceptions from that.

- bogus cast of cp arg to char * in sprintf() call.  cp doesn't suffer from
  unsigned poisoning, so already has type char *.

- no cast of cp2 arg in sprintf() call.  Such a cast can only break the
  warning.  It is unclear if %s format can handle args of type unsigned
  char *.  Even if the behaviour is defined, then I think it ends up
  converting unsigned char to char via a type pun.

The string concatenation can be done even more easily and correctly using
strcat(), but style(9) says to use printf() instead of special methods and
that is a good rule for sprintf() 

Re: svn commit: r349791 - head/sys/vm

2019-07-09 Thread Bruce Evans

On Mon, 8 Jul 2019, Scott Long wrote:


This isn???t the first time I???ve witnessed your passion on this topic.  It 
would
help immensely if there was some documentation, maybe in /sys/sys/param.h,
or maybe even in a manual page, on what a ???click??? is, what a ???db??? is, 
why
they???re important, and how they should be used.  Do you have any
documentation tucked away that could be edited and committed?


I don't have any extra documentation.

I learned about clicks because Minix had them and actually used them in a
nontrivial way (1 click = 16 bytes = real mode segment granularity, and
16-bit ints could could represent the final click address in the real-mode
address space of 1MB but not the size of the whole address space).

Mike Karels gave more details about this.  PDP-11's had 64-bit clicks.  I
think this was also to extend the 16-bit address space in a less bad way
that x86 real mode segments.

Google says that NetBSD has dbtob(9).  This is a link to ctod(9).  This
man page does little more than say "The ctod family of macros can be
used to convert between bytes, pages (''clicks'') and disk blocks" and
expand the abbreviations.  'c' is expanded to 'pages', and there are
no documented macros where 'pages' is abbreviated to 'p'.  The full
list is:
- ctod (spelled ctodb() in FreeBSD),
- dtoc (similarly),
- ctob,
- btoc,
- dbtob (same spelling as in FreeBSD).
- btodb.
One detail is interesting: that the macros make no assumption about
the type of the input parameter (this is clearly wrong since signed
types with negative values don't work when the implementation uses
shifts, floating-point types are further from working, and
non-arithmetic types can't work), and that the caller must ensure that
integer overflow and integer underflow do not occur (here "integer
underflow" is nonsense" -- it means integer overflow to a negative
value).

4.4BSD-Lite2 has these macros with the NetBSD spellings, and also on
i386, tahoe and vax:
- ctos, stoc: core clicks to segments.  All do the identity conversion.
  None are used on any arch.

FreeBSD-1.0 has similar or the same macros as 4.4BSD-Lite2, including
implementation and comments.

FreeBSD-3 doesn't have ctos or stoc, and abbreviates 'disk block' to
'db' consistently, and improves some of the implementations and
comments.

FreeBSD-current is similar to FreeBSD-3, except most of the macros are now
MI and it has lost better comments which were only in the alpha version.

FreeBSD's  actually documents most of these macros
reasonably well in comments.  It just uses different styles and random
grouping.  Only btodb and dbtob end up without a comment giving a hint
about what b and db are.  The comments for dbtoc and ctodb tell you
that a db is a devblk and a c is a page.  Other comments tell you that
a c is a click.

Bruce___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r349791 - head/sys/vm

2019-07-06 Thread Bruce Evans

On Sat, 6 Jul 2019, Doug Moore wrote:


Log:
 Fix style(9) violations involving division by PAGE_SIZE.


It is style violation to even use an explicit division by PAGE_SIZE
instead of the btoc() conversion macro (*).


Modified: head/sys/vm/swap_pager.c
==
--- head/sys/vm/swap_pager.cSat Jul  6 15:34:23 2019(r349790)
+++ head/sys/vm/swap_pager.cSat Jul  6 15:55:16 2019(r349791)
@@ -523,7 +523,7 @@ swap_pager_swap_init(void)
 * but it isn't very efficient).
 *
 * The nsw_cluster_max is constrained by the bp->b_pages[]
-* array (MAXPHYS/PAGE_SIZE) and our locally defined
+* array MAXPHYS / PAGE_SIZE and our locally defined
 * MAX_PAGEOUT_CLUSTER.   Also be aware that swap ops are
 * constrained by the swap device interleave stripe size.
 *


The macro is less readable in comments.


@@ -538,7 +538,7 @@ swap_pager_swap_init(void)
 * have one NFS swap device due to the command/ack latency over NFS.
 * So it all works out pretty well.
 */
-   nsw_cluster_max = min((MAXPHYS/PAGE_SIZE), MAX_PAGEOUT_CLUSTER);
+   nsw_cluster_max = min(MAXPHYS / PAGE_SIZE, MAX_PAGEOUT_CLUSTER);

nsw_wcount_async = 4;
nsw_wcount_async_max = nsw_wcount_async;

Modified: head/sys/vm/vnode_pager.c
==
--- head/sys/vm/vnode_pager.c   Sat Jul  6 15:34:23 2019(r349790)
+++ head/sys/vm/vnode_pager.c   Sat Jul  6 15:55:16 2019(r349791)
@@ -544,8 +544,8 @@ vnode_pager_addr(struct vnode *vp, vm_ooffset_t addres
*rtaddress += voffset / DEV_BSIZE;
...


Using explicit division by DEV_BSIZE instead of the btodb() conversion
macro is another style bug.

(*) The macros use shifts while the divisions use division.  The hard-coded
versions could use shifts too, so there is another set of style bugs from
only using shifts sometimes.  Shifts are faster if the type of the dividend
is signed.

Oops.  The macro also rounds up.  So hard-coding the division is not just
a style bug.  It is wrong unless the dividend is a multiple of the page
size.  This shouldn't be assumed for values like MAXBSIZE.

There are many more style bugs involving btoc():
- 'c' in it means 'click', which might mean a virtual page size while
  PAGE_SIZE might mean the physical page size.  Or vice versa.  dyson
  retired from BSD not long after I asked him to clean this up 20+
  years ago.
- btoc() is the only clearly MI macro for this.  The better-named macros
  amd64_ptob() and i386_ptob() are of course MD.  amd64_ptob() is never
  used in sys/amd64.  i386_ptob() is used 8 times in sys/i386 (all in
  pmap.c), and 1 of these uses is in a macro which is used 22 times.
  These uses give another set of style bugs.  They are just obfuscations
  if clicks are the same as pages, and probably incomplete otherwise.
  However, it is correct for MD code to use physical pages unless it is
  implementing virtual pages.

  These macros don't round up, so they are not equivalent to btoc() even
  if the click size is PAGE_SIZE.
- there is also the better-named macro atop().  This doesn't round up.
  I think it is supposed to be MI.  It is replicated 
  for all arches.  'a' in it means 'address', which is less general than
  'b' for 'byte, so it is a worse name than btop().
- the macro with the best name btop() doesn't exist.

In the opposite direction, there are ctob(), {amd64,i386}_ptob(),
ptoa(), and direct multiplications by PAGE_SIZE and direct shifts by
PAGE_SHIFT.  {amd64,i386}_ptob() is not used even on i386.  This direction
is trickier since the (npages << PAGE_SHIFT) overflows if npages has the
correct type (int).  The caller should convert npages to something like
vm_offset_t before using the macro and the need for this is less obvious
than for a direct expression.  This is of course undocumented except by
the source code which shows:
- ctob(), ptoa() and i386_ptob() need conversion in the caller, but
  amd64_ptob() converts to unsigned long in the macro.  Since the last
  macro is unused, the caller should convert in all used cases.  Coversion
  is most important on 64-bit arches.  On i386, overflow occurs at 2G
  starting with int npages but u_int npages works up to 4G which is
  enough for i386 addresses but not for amd64 addresses or i386-PAE
  byte counts.

I once sprinkled conversions in the macros.  btodb() still uses my old
code for this, where the code is sophisticated so as to avoid using
the long long abomination, but which became mostly nonsense when daddr_t
was expanded from 32 bits to 64.  Since this macro shifts right,
conversion is not really necessary, and conversion to daddr_t gives
much the same pessimations as conversion to the abomination.  dbtodb()
simply converts to daddr_t.  I forget if I wrote that.  btoc() converts
to vm_offset_t, but 

Re: svn commit: r349503 - head/contrib/ipfilter/man

2019-06-28 Thread Bruce Evans

On Fri, 28 Jun 2019, Cy Schubert wrote:


Log:
 Document the -B, binary logfile, and the -C config file options.
 Reference the ipmon.5 man page and ipmon.conf.

 PR:238816
 MFC after: 1 week

Modified:
 head/contrib/ipfilter/man/ipmon.8

Modified: head/contrib/ipfilter/man/ipmon.8
==
--- head/contrib/ipfilter/man/ipmon.8   Fri Jun 28 04:18:10 2019
(r349502)
+++ head/contrib/ipfilter/man/ipmon.8   Fri Jun 28 04:28:32 2019
(r349503)
@@ -7,6 +7,10 @@ ipmon \- monitors /dev/ipl for logged packets
[
.B \-abBDFhnpstvxX


-B was misdocumented as a flag here, and still is.


] [
+.B "\-B "
+] [


This file isn't written in mdoc.  This gives errors starting with
misformatting the SYNOPIS.  The most obvious ones are:
- split lines are not properly indented
- splitting is done in bad places (after '[' for [  ]
- unusual quoting.  mdoc would not put angle brackets and spaces around
  'filename.  These brackets and spaces seem to be mostly hard-coded
  using .B and literals.
- bad rendering or for square brackets around NSI.  These square brackets
  mean optional options as usual, but are not rendered normally.  The .B
  macro apparently gives normal rendering for outer square brackets, but
  the inner square brackets around NSI use the same rendering as the letters.
- various misorderings: -N before -L, -f after -[NLoOPS; NSI randomly
  ordered.

The recent fixes to the usage message have the correct order for [-NLf],
and different misformatting for split lines, so are hard to compare with
the man page.

This commit makes the usage message out of date again.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r349459 - head/sys/sys

2019-06-28 Thread Bruce Evans

On Thu, 27 Jun 2019, Andriy Gapon wrote:


On 27/06/2019 20:37, Bruce Evans wrote:

On Thu, 27 Jun 2019, Andriy Gapon wrote:


On 27/06/2019 18:47, Bruce Evans wrote:

On Thu, 27 Jun 2019, Andriy Gapon wrote:


Log:
??upgrade the warning printf-s in bus accessors to KASSERT-s

??After this change sys/bus.h includes sys/systm.h.


This is further namespace pollution.?? sys/systm.h is a prerequiste for
all kernel headers except sys/param.h and the headers that that includes,
since any kernel header (except sys/param.hm etc.) may have inlines which
use features in systm.h, e.g., KASSERT() or an inline function.


what do you think about amending style(9) to require that if sys/systm.h is to
be included, then it must be included before any other header except for
sys/param.h (and possibly sys/cdefs.h) ?


It is not a style matter.


I know... but style(9) documents sys/param.h for similar reasons.


sys/systm.h is just a prerequisite for almost
all kernel code.?? Perhaps this can be enforced using #ifdef magic even
for headers that don't currently use it.?? If it is to be included nested,
then sys/param.h is the place to include it, but I don't like that since
it is even less related to parameters than sys/param.h, and this would be
a regression from minor depollution of sys/param.h.

sys/systm.h is also kernel-only, and as you found, including it nested
tends to break applications, so other headers that have the bug of
including it tend to have _KERNEL ifdefs to avoid including it in
applications.?? This is so fundamental that it doesn't have a "No
user-serviceable parts inside" ifdef.


I think that there is a trivial fix to my commit: moving the sys/systm.h include
to the _KERNEL section of sys/bus.h.  That's where its definitions are actually
used.
But I agree that there should be a better approach.


I did a quick check of how many .c files are missing includes of sys/systm.h.
In an old version of FreeBSD, my normal kernel has about 1100 object files,
and about 89 of these broke when a KASSERT() was added to sys/bus.h without
adding the pollution.  That is many more than I expected.

Many of these errors are in automatically generated bus if.c files.  E.g.,
the include list in acpi_if.c is:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "acpi_if.h"

Here sys/bus.h and sys/types.h and the contrib include are in the .m file,
and the others are automatically generated.  Including sys/types.h is
nonsense since sys/param.h already included it and sys/bus.h already used
typedefs in it.  The generation also misorders sys/queue.h and mangles
the formatting of the contrib include (in the .m file, it is separated
by spaces).

Here the .m file should know sys/bus.h's prerequisites and add them all
except sys/param.h and sys/systm.h, or maybe the include of sys/bus.h
should be auto-generated too (my test kernel has 25 foo_if.c files and
21 of these include sys/bus.c).

Most of the generated if.c files include sys/systm.h by nested pollution
anyway.  Just not early enough to actually work.  E.g., in acpi_if.c,
the above 8 includes expand to 45 lines, 144 words and 2679 chars in
.depend.acpi_if.o according to wc.  The word count of 144 is
approximately the number of includes.  sys/systm.h is first included
deeply nested in contrib//acpi.h.

11 of the 25 generated foo_if.c end up never including sys/systm.h.

Of the remaining 64 files that fail to compile, all except 7 including
1 maintained by me (cy_pci.c) *blush* end up including sys/systm.h.
The other 57 apparently include it either misordered in the .c file
or via nested pollution.

After removing all nested includes of sys/systm.h in  headers, only
another 50 object files fail to build.  most of the extras are for
libkern functions (20 for str*() alone).  libkern was polluted.h relatively
recently as part of unimproving the implementation of bcd conversion APIs
from macros to inlines with KASSERT()s.  The KASSERT()s were a bad fix for
missing sanity checks of bcd data in callers.

Bruce___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r349459 - head/sys/sys

2019-06-27 Thread Bruce Evans

On Thu, 27 Jun 2019, Andriy Gapon wrote:


On 27/06/2019 18:47, Bruce Evans wrote:

On Thu, 27 Jun 2019, Andriy Gapon wrote:


Log:
??upgrade the warning printf-s in bus accessors to KASSERT-s

??After this change sys/bus.h includes sys/systm.h.


This is further namespace pollution.?? sys/systm.h is a prerequiste for
all kernel headers except sys/param.h and the headers that that includes,
since any kernel header (except sys/param.hm etc.) may have inlines which
use features in systm.h, e.g., KASSERT() or an inline function.


what do you think about amending style(9) to require that if sys/systm.h is to
be included, then it must be included before any other header except for
sys/param.h (and possibly sys/cdefs.h) ?


It is not a style matter.  sys/systm.h is just a prerequisite for almost
all kernel code.  Perhaps this can be enforced using #ifdef magic even
for headers that don't currently use it.  If it is to be included nested,
then sys/param.h is the place to include it, but I don't like that since
it is even less related to parameters than sys/param.h, and this would be
a regression from minor depollution of sys/param.h.

sys/systm.h is also kernel-only, and as you found, including it nested
tends to break applications, so other headers that have the bug of
including it tend to have _KERNEL ifdefs to avoid including it in
applications.  This is so fundamental that it doesn't have a "No
user-serviceable parts inside" ifdef.

Bruce___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r349459 - head/sys/sys

2019-06-27 Thread Bruce Evans

On Thu, 27 Jun 2019, Andriy Gapon wrote:


Log:
 upgrade the warning printf-s in bus accessors to KASSERT-s

 After this change sys/bus.h includes sys/systm.h.


This is further namespace pollution.  sys/systm.h is a prerequiste for
all kernel headers except sys/param.h and the headers that that includes,
since any kernel header (except sys/param.hm etc.) may have inlines which
use features in systm.h, e.g., KASSERT() or an inline function.


Modified: head/sys/sys/bus.h
==
--- head/sys/sys/bus.h  Thu Jun 27 14:26:57 2019(r349458)
+++ head/sys/sys/bus.h  Thu Jun 27 15:07:06 2019(r349459)
@@ -35,6 +35,7 @@
#include 
#include 
#include 
+#include 


This header used to be relatively clean, with no polluting includes.

The following low-quality headers in sys already include sys/systm.h:

- capsicum.h:#include 
- fail.h:#include 
- fbio.h:#include 
- intr.h:#include 
- libkern.h:#include 
- malloc.h:#include 
- mbuf.h:#include 
- pmckern.h:#include 
- proc.h:#include 
- refcount.h:#include 
- seqc.h:#include 
- sf_buf.h:#include 
- zutil.h:#include 

This is especially bad in:
- libkern.h.  systm.h includes libkern.h, so this recurses.  The recursion
  is bounded by the reinclude guard.  libkern.h was broken by adding
  KASSERT()s to it.  It is a leaf header, so must be written carefully.
- malloc.h and mbuf.h.  I fixed all the include pollution in them.  They
  are now much more polluted than before I cleaned them
- proc.h.  Almost everything includes this.  Including sys/systm.h in it
  hdes the bug of not including sys/systm.h in the correct place in .c files.


/**
 * @defgroup NEWBUS newbus - a generic framework for managing devices
@@ -813,12 +814,9 @@ static __inline type varp ## _get_ ## var(device_t dev
int e;  \
e = BUS_READ_IVAR(device_get_parent(dev), dev,  \
ivarp ## _IVAR_ ## ivar, );   \
-   if (e != 0) {   \
-   device_printf(dev, "failed to read ivar " \
-   __XSTRING(ivarp ## _IVAR_ ## ivar) " on bus %s, " \
-   "error = %d\n",   \
-   device_get_nameunit(device_get_parent(dev)), e);\
-   }   \
+   KASSERT(e == 0, ("%s failed for %s on bus %s, error = %d",\
+   __func__, device_get_nameunit(dev), \
+   device_get_nameunit(device_get_parent(dev)), e));   \
return ((type) v);  \
}   \
\


Inline functions in headers generally cause namespace pollution, like here.
Some headers use macros which don't have that problem.  mbuf.h used to be
like that.  The cleaned version of it in FreeBSD-4 includes only
sys/queue.h.  It has rotted to include sys/systm.h, sys/refcount.h,
vm/uma.h. sys/lock.h and sys/sdt.h.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r349248 - in head/sys: fs/fifofs kern sys

2019-06-21 Thread Bruce Evans

On Thu, 20 Jun 2019, Alan Somers wrote:


Log:
 fcntl: fix overflow when setting F_READAHEAD

 VOP_READ and VOP_WRITE take the seqcount in blocks in a 16-bit field.
 However, fcntl allows you to set the seqcount in bytes to any nonnegative
 31-bit value. The result can be a 16-bit overflow, which will be
 sign-extended in functions like ffs_read. Fix this by sanitizing the
 argument in kern_fcntl. As a matter of policy, limit to IO_SEQMAX rather
 than INT16_MAX.
...
Modified: head/sys/kern/vfs_vnops.c
==
--- head/sys/kern/vfs_vnops.c   Thu Jun 20 22:21:42 2019(r349247)
+++ head/sys/kern/vfs_vnops.c   Thu Jun 20 23:07:20 2019(r349248)
@@ -499,7 +499,8 @@ sequential_heuristic(struct uio *uio, struct file *fp)
 * closely related to the best I/O size for real disks than
 * to any block size used by software.
 */
-   fp->f_seqcount += howmany(uio->uio_resid, 16384);
+   fp->f_seqcount += MIN(IO_SEQMAX,
+   howmany(uio->uio_resid, 16384));
if (fp->f_seqcount > IO_SEQMAX)
fp->f_seqcount = IO_SEQMAX;


This already limited the result to IO_SEQMAX.  Now it limits the result to
IO_SEQMAX twice.

Using MIN() is a style bug.  4.4BSD removed the MIN() macro from the kernel
and replaced it by *min() inline functions.  MIN() was restored because
too much contribed code used it, but it should not be used in core code.

However, *min() is not type-generic, so it is hard to use.  Using

f_seqcount = imin(IO_SEQMAX, howmany(uio->uio_resid, 16384));

would restore the overflow bug.  This code worked originally when uio_resid
had type int.  It was broken by changing uio_resid's type to ssize_t.
This makes howmany(uio->uio_resid, 16384) have type ssize_t too, and its
value overflows on assignment to "int f_seqcount" before the value is
clamped to IO_SEQMAX, whenever uio_resid is especially preposterously
large (2G * 16384) on 64-bit systems which pretend to support such silly
i/o sizes.

imin() is as bad as the blind assignment to an int, since its prototype
cause blind conversion to int.  I have some macros for *min() which
optionally detect such type errors or just do much the same as MIN()
(but using inline functions), but these are not quite of production
quality.  The case where one arg has a signed type and the other arg
has a signed type is hardest to handle.  This has sign extension or
unsign extension bugs in general.  MIN() blindly does the extension.


The overflow usually only causes negative f_seqcount which should be
treated as 0.


return (fp->f_seqcount << IO_SEQSHIFT);

Modified: head/sys/sys/file.h
==
--- head/sys/sys/file.h Thu Jun 20 22:21:42 2019(r349247)
+++ head/sys/sys/file.h Thu Jun 20 23:07:20 2019(r349248)
@@ -179,7 +179,10 @@ struct file {
/*
 *  DTYPE_VNODE specific fields.
 */
-   int f_seqcount; /* (a) Count of sequential accesses. */
+   union {
+   int16_t f_seqcount; /* (a) Count of sequential accesses. */
+   int f_pipegen;
+   };
off_t   f_nextoff;  /* next expected read/write offset. */
union {
struct cdev_privdata *fvn_cdevpriv;


f_seqcount should still have type int.  Conversion of any type smaller than
int to int just wastes time, and int16_t is a bogus type for holding values
limited to 0x7F.

int for f_seqcount costs no space, since f_pipegen still has the correct
type and the union is padded to at least the size of its largest member.

This struct has delicate ordering which usually minimizes padding,
although it violates style(9) for most integer members.  Before
f_seqcount, there are some pointers, then 2 shorts and 2 u_int's, so
64-bit alignment occurs after f_seqcount on 64-bit arches, just in
time for there to be no padding before the 64-bit f_offset.  style(9)
requires sorting all the 64-bit types first.

My macros look like:

XX #define __min(x, y)  \
XX (\
XX  (sizeof(x) == 8 || sizeof(y) == 8) ?\
XX  ((__typeof(x))-1 == -1 && (__typeof(y))-1 == -1) ?  \
XX  _qmin((x), (y)) \
XX  :   \
XX  _uqmin((x), (y))\
XX  :   \
XX  ((__typeof(x))-1 == -1 && (__typeof(y))-1 == -1) ?  \
XX  _imin((x), (y)) \
XX  :  

Re: svn commit: r349233 - head/sys/sys

2019-06-21 Thread Bruce Evans

On Thu, 20 Jun 2019, Warner Losh wrote:


On Thu, Jun 20, 2019, 11:44 AM Bruce Evans  wrote:


On Thu, 20 Jun 2019, Alan Somers wrote:


On Thu, Jun 20, 2019 at 10:43 AM Bruce Evans 

wrote:

Summary:  and the headers that it includes should declare
minimal types to compile (so __int64_t is enough).  Most uses of this
header require including domain-specific headers which declare the
relevant data structures.


Bruce, would you be satisfied by switching from  to
 and from int64_t to __int64_t?


Not quite.  The kernel block number type is daddr_t, and [__]int64_t is
a hard coding of that.  Hard-coding of typedefs is good for reducing
namespace pollution, but it is not done for the nearby use of off_t.

Unfortunately, daddr_t is only declared in .

[... related type/units errors in ffs and ext2fs]
Using a generic int64_t type in all interfaces would avoid some of these
bugs, so I don't mind using it for the API.  Just add a note that it must
be large enough to represent all useful values of daddr_t.


Maybe we should add a __daddr_t define to sys/_types.h? And the usual
reshuffling. That would also fix the namespace pollution.


OK.  ABI's should use only fixed-width types to be stable, and APIs should
use only basic types to be stable, but avoiding typedefs (except to fixed-
width types) would be a larger project, with few existing examples.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r349233 - head/sys/sys

2019-06-20 Thread Bruce Evans

On Thu, 20 Jun 2019, Alan Somers wrote:


On Thu, Jun 20, 2019 at 10:43 AM Bruce Evans  wrote:

Summary:  and the headers that it includes should declare
minimal types to compile (so __int64_t is enough).  Most uses of this
header require including domain-specific headers which declare the
relevant data structures.


Bruce, would you be satisfied by switching from  to
 and from int64_t to __int64_t?


Not quite.  The kernel block number type is daddr_t, and [__]int64_t is
a hard coding of that.  Hard-coding of typedefs is good for reducing
namespace pollution, but it is not done for the nearby use of off_t.

Unfortunately, daddr_t is only declared in .

The type daddr_t seems to be correct, but ffs conflates it with
ufs2_daddr_t.  It is only for blocks of size DEV_BSIZE, while fs blocks
are usually larger.  The conflation is just a style bug because 64 bits
should be large enough for anyone and ffs does the necessary conversions
between DEV_BSIZE-blocks and fs-blocks.

ext2fs seems to be more broken in this area.  It doesn't have
ext2fs_daddr_t, but hard-codes this as int32_t or int64_t.  int32_t
became very broken when ext2fs started attempting to support unsigned
block numbers.  Now, ext2_bmap() corrupts "daddr_t a_bn" to "int32_t
bn" when it calls ext4_bmapext().  This has a chance of working via
unsign-extension bugs provided a_bn fits in uint64_t.  It is sure to
fit for a valid a_bn, but perhaps your new ioctl allows probing for
panics using invalid a_bn.  ext2_bmap() also calls ext2_bmaparray().
That used to have essentially the same style bugs as ffs (with the
ext2fs type corresponding to ufs2_daddr_t spelled int32_t), but it now
correctly uses daddr_t.  Internally, it misuses daddr_t for ext2fs
block numbers, and there is an ext2fs block number type after all
(e2fs_lbn_t = int64_t) which it uses only for metalbn.

It looks like the older ext2fs code was fixed, especially if older ext2fs
is limited to int32_t block numbers, but the ext4 case is quite broken
since unsign extension bugs don't help it.  a_bn starts as int64_t, then
is truncated to the function arg "int32_t bn", then the function assigns bn
to "int64_t lbn" and doesn't use bn again.

Using a generic int64_t type in all interfaces would avoid some of these
bugs, so I don't mind using it for the API.  Just add a note that it must
be large enough to represent all useful values of daddr_t.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r349233 - head/sys/sys

2019-06-20 Thread Bruce Evans

On Thu, 20 Jun 2019, Alan Somers wrote:


On Thu, Jun 20, 2019 at 9:14 AM Ian Lepore  wrote:


On Thu, 2019-06-20 at 14:35 +, Alan Somers wrote:

Author: asomers
Date: Thu Jun 20 14:35:28 2019
New Revision: 349233
URL: https://svnweb.freebsd.org/changeset/base/349233

Log:
  #include  from sys/filio.h

  This fixes world build after r349231


This increases the bugs in r349231 by adding more undocumented namespace
pollution.


Modified: head/sys/sys/filio.h
=
=
--- head/sys/sys/filio.h  Thu Jun 20 14:34:45 2019(r349232)
+++ head/sys/sys/filio.h  Thu Jun 20 14:35:28 2019(r349233)
@@ -40,6 +40,7 @@
 #ifndef  _SYS_FILIO_H_
 #define  _SYS_FILIO_H_

+#include 
 #include 

 /* Generic file-descriptor ioctl's. */


I wonder... is this one of those situations where it is better to use
__int64_t in the struct, then #include ?  I think the net
effect there would be less pollution with other types?  I've never seen
written guidance about when to use the __names and _types.h, but I've
always had the general impression that if you have to include a header
from another system header, it's better to use the _header.h if it
exists.


Good question.  grep shows almost equal numbers of each (37 types.h
and 33 _types.h) in sys/sys.  Do you think I should change it?


Only low quality headers include .

r349231 adds a struct declaration with an int64_t in it.  Everything is
undocumented of course, so one knows if this header declares all the
types needed to use it.  If it only declared __int64_t and used that,
then users would have to know to use __int64_t or to include a header
that declares int64_t in order to use the struct properly (e.g.,
bounds checking of the __int64_t member requires knowing its type).
This is a bit inconvenient.  However, since everything is undocumented,
users have to read the header to see what is in it anyway, so they can
see that it uses __int64_t just as easily as they can see the name of
the struct member of that type.

Higher quality headers usually declare all the standard types that they
use.  Some even document the types that they declare.

filio.h is not referenced in any man page.  It is normally used by
including the omnibus header .   is documented
well enough to require it to declare all the types that it uses.  This
follows from the SYNOPSIS for ioctl(2) -- since no preqrequisites for
 are given, it must not depend on other headers.

ioctl(2) otherwise documents about 1% of the things needed to use it.
No one knows what macros and types  defines/declares.
However, the headers included by  used to be careful
about namespace pollution.  They didn't do much more than #define lots
of macros and used only a few types and mostly only basic types.  This
has rotted a bit.

r349231 added the following bugs:
- use of int32_t, and no documentation of this
- namespace-polluting struct member names bn, runp and runb, and no
  documentation of this
- comment not terminated by a ".".  This is the first instance of this
  bug in the file.
- space instead of tab after #define.  This is the first instance of this
  bug in the file.

Previous bitrot in filio.h:
- namespace-polluting struct member names len and buf, and no documentation
  of this.   All struct member names in the file begin with fio, and this
  would not be namespace pollution if it were documented.
- FIOSEEKDATA and FIOSEEKHOLE use the undeclared type off_t.  This doesn't
  break including , since there is only a problem if these
  macros are used.  These macros are of course undocumented, so the header
  must be read to even know that they exist and then it is easy to see that
  off_t must be declared to use them.

Use of uint32_t and u_long, and function parameter names in the application
namespace are not problems since they are under a _KERNEL ifdef.

The other headers included by  are sys/ioccom.h, sys/sockio.h
and sys/ttycom.h:

sys/ioccom.h:
Mostly implementation details; still fairly clean.

sys/sockio.h:
Still defines only macros and doesn't define any of the types used by these
macros.  Clearly,  should _not_ declare all of these types, or
even one.  Defining all of them might require including all socket and
network headers.  Since there is no documentation, users must read this
header to see which type they need, then read the header that declares
that type to see what its prerequisites are...

sys/ttycom.h:
Like sys/sockio.h, but a hundred times simpler.  The only undeclared types
that it uses are struct timeval and struct termios.

Summary:  and the headers that it includes should declare
minimal types to compile (so __int64_t is enough).  Most uses of this
header require including domain-specific headers which declare the
relevant data structures.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, 

Re: svn commit: r349029 - head/sys/kern

2019-06-14 Thread Bruce Evans

On Fri, 14 Jun 2019, Alexander Motin wrote:


On 14.06.2019 08:58, Bruce Evans wrote:

On Fri, 14 Jun 2019, Alexander Motin wrote:


Log:
??Update td_runtime of running thread on each statclock().

??Normally td_runtime is updated on context switch, but there are some
kernel
??threads that due to high absolute priority may run for many seconds
without
??context switches (yes, that is bad, but that is true), which means their
??td_runtime was not updated all that time, that made them invisible
for top
??other then as some general CPU usage.

??MFC after:?? 1 week
??Sponsored by:?? iXsystems, Inc.


This and more is supposed to be done in calcru().?? It is also necessary to
adjust for the current timeslice.

I thought that calcru() was fixed, but the fix seems to be only in my
version of FreeBSD-5.2.

The bug seems to be in fill_kinfo_proc_only().?? calcru() should update
td_runtime for all threads in the proc (and sum into rux_rutime),


...


td_runtime is updated in one other place: in rufetchtd(), but this function
has the same bug eas everywhere else -- it only updates the runtimes for
curthread.


I think it has very simple reason -- now each CPU measures CPU time in
its own time units, since cpu_ticks() are not synchronized and can not
be compared between different CPUs, so to update td_runtime of another
running thread you would need to switch to that CPU, or somehow else get
the value (cache it periodically?).


I forgot about that bugfeature in the cpu ticker.


I see in your code you are using binuptime() calls instead of
cpu_ticks().  I suppose it fixes many problems, since it is globally
synchronous, but there was a reason why cpu_ticks() exists -- it is
cheaper on system non-synchronized TSC.  May be we could reconsider
that, giving up on old platforms, expecting all new one to not have this
problem, but for right now I think my patch is good enough to make top
sane again, that annoyed me for years.


It was written before the cpu ticker existed.

cpu_ticks() exists because bintime() is too slow if the timecounter hardware
is too slow.  i8254 timecounter hardware takes about 5 usec, ACPI timer
about 1 usec, and HPET many hundreds of nsec.  And of course,
non-synchronized TSCs make the TSC unusable as a timecounter, so require
use of a slow timecounter.  Some systems don't have a TSC, so they use a
timecounter for the cpu ticker anyway.

There are many other bugs in the cpu ticker which only became not too bad
when P-state invariant TSCs became common.  The largest one is that all
ticks are scaled at the current cpu ticker frequency.  If synchronized
P-state invariant TSCs are available, then the cpu ticker reduces to
a micro-optimization.

My code is used mainly on UP systems with TSC timecounters.  I don't have
any systems without a TSC, and UP avoids the problems of synchronization,
and not throttling the CPU avoids the problem of the frequency changing,
and I never noticed the micro-pessimization of using bintime() for the
cpu ticker.

I never noticed the problem in -current either, though I use my version of
SCHED_4BSD with lots of tuning to reduce context switches.  The tuning often
results in threads running for a full quantum (100 msec) before switching,
but I never noticed threads not switching for several seconds.

Bruce___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r349029 - head/sys/kern

2019-06-14 Thread Bruce Evans

On Fri, 14 Jun 2019, Alexander Motin wrote:


Log:
 Update td_runtime of running thread on each statclock().

 Normally td_runtime is updated on context switch, but there are some kernel
 threads that due to high absolute priority may run for many seconds without
 context switches (yes, that is bad, but that is true), which means their
 td_runtime was not updated all that time, that made them invisible for top
 other then as some general CPU usage.

 MFC after: 1 week
 Sponsored by:  iXsystems, Inc.


This and more is supposed to be done in calcru().  It is also necessary to
adjust for the current timeslice.

I thought that calcru() was fixed, but the fix seems to be only in my
version of FreeBSD-5.2.

The bug seems to be in fill_kinfo_proc_only().  calcru() should update
td_runtime for all threads in the proc (and sum into rux_rutime), but
fill_kinfo_proc_only() uses rux_runtime to initialize ki_runtime before
calling calcru(), so sees a stale value.  This was broken in r132855
(the initialization of ki_runtime was moved too early as part of a fix
for zombies).

Using calcru() for its side effect is a bit magic.  get_thread_cputime()
does this less hackishly for curthread (by adding the timeslice without
updating td_runtime), but is broken for other threads (by using the
stale td_runtime).

td_runtime is unavailable in userland.  top and ps can only see ki_runtime
which is per-process.

Actually, calcru() seems to have the same bug as get_thread_cputime().
This is fixed in my version of FreeBSD-5-2, but is clearly broken in
plain FreeBSD-FreeBSD-5.2, and -current seems to be even more broken
than plain 5.2 -- it is missing the large comment about this bug that
I added in r130858.  -current first updates td_runtime for curthread.
Then it loops over all threads in the process, but does nothing unless
td_incruntime != 0, and when td_incruntime != 0 it updates rux_runtime
using the value in td_incruntime, and this value is stale except for
curthread.

td_runtime is updated in one other place: in rufetchtd(), but this function
has the same bug eas everywhere else -- it only updates the runtimes for
curthread.

Here is my fix for this in FreeBSD-5.2:

XX Index: kern_resource.c
XX ===
XX RCS file: /home/ncvs/src/sys/kern/kern_resource.c,v
XX retrieving revision 1.140
XX diff -u -2 -r1.140 kern_resource.c
XX --- kern_resource.c  21 Jun 2004 17:46:27 -  1.140
XX @@ -702,18 +720,80 @@
XX  struct timeval *ip;
XX  {
XX -struct bintime bt, rt;
XX -struct timeval tv;
XX +struct bintime bt;
XX +struct rusage_ext rux;

-current already has most of the infrastructure for this -- I invented
rusage_ext partly to fix this problem, and -current has a more sophisticated
version of rusage_ext.

-current also uses cputicks instead of bintimes.

XX  struct thread *td;
XX -/* {user, system, interrupt, total} {ticks, usec}; previous tu: */
XX -u_int64_t ut, uu, st, su, it, iu, tt, tu, ptu;
XX -int problemcase;
XX +int bt_valid, proc_locked, sched_locked;
XX 
XX -	mtx_assert(_lock, MA_OWNED);

XX -/* XXX: why spl-protect ?  worst case is an off-by-one report */
XX +proc_locked = mtx_owned(>p_mtx);
XX +sched_locked = mtx_owned(_lock);
XX +if (!proc_locked && !sched_locked)
XX +PROC_LOCK(p);
XX +if (!sched_locked)
XX +mtx_lock_spin(_lock);

This also has some restructuring that -current already has in a more
sophisticated way.

XX +rux = p->p_rux;
XX +bt_valid = 0;
XX +FOREACH_THREAD_IN_PROC(p, td) {
XX +if (TD_IS_RUNNING(td)) {
XX +/*
XX + * Adjust for the current time slice.  This is
XX + * important since the adjustment is on the order
XX + * of a time quantum, which is much greater than
XX + * the precision of binuptime().
XX + */
XX +KASSERT(td->td_oncpu != NOCPU,
XX +("calcru: running thread has no CPU"));
XX +if (!bt_valid) {
XX +binuptime();
XX +bt_valid = 1;
XX +}
XX +bintime_sub(,
XX +_find(td->td_oncpu)->pc_switchtime);
XX +if (bt.sec < 0) {
XX +printf(
XX +"calcru: negative delta-runtime of %jd sec + %jd wsec for pid %d 
(%s)\n",
XX +(intmax_t)bt.sec, bt.frac,
XX +p->p_pid, p->p_comm);
XX +bt.sec = 0;
XX +bt.frac = 0;
XX +}
XX +bintime_add(_runtime, );
XX +}
XX +}
XX +if (!sched_locked)
XX +mtx_unlock_spin(_lock);

That is the main part of the fix.  It is necessary to loop over all threads
in the 

Re: svn commit: r348847 - head/sys/sys

2019-06-10 Thread Bruce Evans

On Mon, 10 Jun 2019, Ian Lepore wrote:


On Mon, 2019-06-10 at 07:49 -0600, Warner Losh wrote:

On Mon, Jun 10, 2019, 7:44 AM Conrad Meyer  wrote:


On Mon, Jun 10, 2019 at 2:10 AM T??l Coosemans 
wrote:

On Mon, 10 Jun 2019 05:28:04 + (UTC) Dmitry Chagin
 wrote:

...
URL: https://svnweb.freebsd.org/changeset/base/348847
Log:
  Use C11 anonymous unions.

Modified: head/sys/sys/ucred.h


...

Isn't this a userland header that should work with non-C11
compilers?

...
Why would one expect userland headers to work with non-C11 (gnu89)
compilers?

...
Because those compilers can choose non c11 variants of the language?


Do we promise that userland will compile with -std=c89?  I hope not.


Only headers and libraries should support -std=c89.   has
lots of support for compilers and POSIX versions going back to K C,
and only the K parts are completely broken.

FreeBSD also has the c89 and c99 utilities.  These require c89 and c99
headers to work under FreeBSD.  c89 uses CFLAGS -std=iso9899:199409
-pedantic.  I don't see how a 1994 standard can be correct for c89,
but -pedantic here might avoid the bug that -std=cxx doesn't actually
gives standard cxx, especially for clang.  c99 uses -std=iso9899:1999
-pedantic.  So anonymous unions are correctly disallowed by both c89
and c99.

At least the following headers still compile with c89: sys/types.h,
stdio.h, stdlib.h, the old version of sys/ucred.h.


Anonymous unions may be a c11 feature, but they're also available with
-std=gnu99, which I think is how we compile userland.


That is only the default, only for for parts of userland controlled by us.
Non-FreeBSD makefiles get at most the POSIX CFLAGS (something like -O)
from sys.mk if they use FreeBSD make, and something similar using gmake.


I think -std=gnu99 is how we should also compile the kernel, and I
think Bruce has been trying to say that for several years (but I'm not
sure, because the emails that seem to say so are always so full of
semi-related extraneous material that it's hard to be sure what they're
saying).


-std can be forced for kernel builds and other pure FreeBSD builds, but
then it should be the correct one.

bsd.sys.mk only directly supports the user selecting the following standards:
- c89 or c90
- c94 or c95 (the c89 utility gives -std=c94, not -std=c89)
- c99
- gnu99 (default)
Newer and more useful old standards like gnu89 are hard to select.  The
user must set the undocumented variable CSTD even to change the default to
c89/90/94/95.  Adding -std=whatever to CFLAGS only works if it happens to
be added after -std=${CSTD}.

Bruce___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r348843 - head/sys/vm

2019-06-10 Thread Bruce Evans

On Mon, 10 Jun 2019, Shawn Webb wrote:


On Mon, Jun 10, 2019 at 03:07:11AM +, Doug Moore wrote:

...
Log:
  There are times when a len==0 parameter to mmap is okay. But on a
  32-bit machine, a len parameter just a few bytes short of 4G, rounded
  up to a page boundary and hitting zero then, is not okay. Return
  failure in that case.
...
/* Adjust size for rounding (on both ends). */
size += pageoff;/* low end... */
-   size = (vm_size_t) round_page(size);/* hi end */
+   /* Check for rounding up to zero. */
+   if (round_page(size) < size)
+   return (EINVAL);


The mmap(2) manpage says that len==0 results in EINVAL, so the manpage
needs updating.


The man page doesn't say that only len == 0 results in EINVAL, so it is
not incorrect.

However, the errno here is incorrect.  POSIX specifies that the errno is
ENOMEM if MAP_FIXED was specified, and the range [addr,addr+len) exceeds
that allowed for the address space of the process; or, if MAP_FIXED was
not specified and there is insufficient room in the address space to effect
the mapping.  There are 2 other meanings for ENOMEM in POSIX.1-2001.

The man page documents ENOMEM, but only has a small fraction of the above
case, and no other cases.  It says that the errno is ENOMEM if MAP_FIXED was
specified and the addr argument was not available, or MAP_ANON was specified
and insufficient memory was available.  Who knows what it means for the addr
argument to be no available?

The other cases specified by POSIX but not the man page are: (1) under the
ML extension, if the mapping could not be locked...  (1a) MAP_FIXED or
MAP_PRIVATE was specified and the implementation does not support this
(but FreeBSD does support this, at least for most file types).  (2) under
the TYM extension, not enough resources in the typed memory object
designated by filedes...


I'm curious what "there are times" refers to. Can you or the original
reporter elaborate those cases?


When len == 0 is actually a parameter, and with other parameters specifying
that len == 0 is meaningful.

The code has various style bugs starting with renaming the len parameter to
a size parameter for a layered function.  So it is not actually the len
parameter that is adjusted, but adjusting it is still a style bug since it
reuses a function parameter so the original parameter is harder to describe
and to debug.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r348843 - head/sys/vm

2019-06-10 Thread Bruce Evans

On Mon, 10 Jun 2019, Doug Moore wrote:


Log:
 There are times when a len==0 parameter to mmap is okay. But on a
 32-bit machine, a len parameter just a few bytes short of 4G, rounded
 up to a page boundary and hitting zero then, is not okay. Return
 failure in that case.


Some overflows still occur.

The problem is not limited to 32-bit machines.  The first overflow is for
len parameter just a few bytes short of SIZE_MAX added to a page offset of
a few bytes.  This overflows to a small value.  Then rounding up to a page
boundary doesn't overflow, but gives 0 or PAGE_SIZE, so the new overflow
check doesn't work and overflow still occurs.

The second overflow is for a len parameter just a few bytes short of
SIZE_MAX with the first overflow not occurring (usually because the offset
is 0).  This is now detected.


 Reported by: pho
 Reviewed by: alc, kib (mentor)
 Tested by: pho
 Differential Revision: https://reviews.freebsd.org/D20580

Modified:
 head/sys/vm/vm_mmap.c

Modified: head/sys/vm/vm_mmap.c
==
--- head/sys/vm/vm_mmap.c   Sun Jun  9 22:55:21 2019(r348842)
+++ head/sys/vm/vm_mmap.c   Mon Jun 10 03:07:10 2019(r348843)
@@ -257,7 +257,10 @@ kern_mmap(struct thread *td, uintptr_t addr0, size_t s

/* Adjust size for rounding (on both ends). */
size += pageoff;/* low end... */


The first overflow occurs here.  Except in special cases, pageoff can be
anything between 0 and PAGE_SIZE - 1, and size can be anything between 0
and SIZE_MAX.


-   size = (vm_size_t) round_page(size);/* hi end */
+   /* Check for rounding up to zero. */
+   if (round_page(size) < size)
+   return (EINVAL);
+   size = round_page(size);/* hi end */

/* Ensure alignment is at least a page and fits in a pointer. */
align = flags & MAP_ALIGNMENT_MASK;


This bug was implemented in r239247 and affects all versions of FreeBSD
newer than FreeBSD-7.  Before then, FreeBSD used the bogus 4.4BSD check
that (ssize_t)uap->len >= 0 (else return EINVAL).  This behaviour was
even documented.  POSIX doesn't allow this -- it requires ENOMEM for
invalid ranges, though it should require EOVERFLOW for ranges that are
so invalid that they overflow something.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r348419 - in head: crypto/heimdal/lib/ipc share/man/man4 sys/compat/linux sys/kern sys/sys usr.sbin/mountd

2019-06-04 Thread Bruce Evans

On Tue, 4 Jun 2019, Gleb Smirnoff wrote:


On Thu, May 30, 2019 at 02:24:27PM +, Dmitry Chagin wrote:
D> Author: dchagin
D> ...
D> Log:
D>   Complete LOCAL_PEERCRED support. Cache pid of the remote process in the
D>   struct xucred. Do not bump XUCRED_VERSION as struct layout is not changed.
D>
D>   PR: 215202
D>   Reviewed by:tijl
D>   MFC after:  1 week
D>   Differential Revision:  https://reviews.freebsd.org/D20415
...
D> Modified: head/sys/sys/ucred.h
D> 
==
D> --- head/sys/sys/ucred.h  Thu May 30 14:21:51 2019(r348418)
D> +++ head/sys/sys/ucred.h  Thu May 30 14:24:26 2019(r348419)
D> @@ -87,10 +87,14 @@ struct xucred {
D>   uid_t   cr_uid; /* effective user id */
D>   short   cr_ngroups; /* number of groups */
D>   gid_t   cr_groups[XU_NGROUPS];  /* groups */
D> - void*_cr_unused1;   /* compatibility with old ucred */
D> + union {
D> + void*_cr_unused1;   /* compatibility with old ucred */
D> + pid_t   _pid;
D> + } _cr;
D>  };
D>  #define  XUCRED_VERSION  0
D>
D> +#define  cr_pid _cr._pid

Why don't use C99 in 2019 instead of preprocessor define? Should be

union {
void*_cr_unused1;   /* compatibility with old ucred */
pid_t   cr_pid;
};


Anonymous unions are a gnu89 extension.  Only broken C99 compilers like
clang -std=c99 accept them.

The kernel makefiles (kern.mk, kern.pre.mk and kmod.mk) are still very
broken in this area:

- kern.mk forces CSTD=c99.  This prevents users using their preferred
  standard or even the correct standard.  These bugs are missing in
  bsd.sys.mk.  It uses the correct standard gnu99, and assigns it using
  ?= to not prevent users using their preferred standard or even the
  correct standard.  But see the commit logs fo bsd.sys.mk.  It took
  several rounds of churning to get this almost right.  Using c99 for
  the standard is even wronger in the kernel than in userland, since
  the kernel uses nonstandard extensions relatively much more often
  than userland.

- after this forcing, there is an ifdef copied (except for removing k
  support) from bsd.kern.mk.  Since CSTD is forced, in the kernel this
  is an obfuscated way of adding the obfuscated standard name iso9899:1999.
  De-obfuscating 13 lines of this gives

  CFLAGS+=  -std=iso9899:1999

- clang dishonors this request to be a C99 compiler and doesn't even warn
  about anonymous unions in the kernel.  It takes -pedantic as well as
  -std=c99 to make clang resemble a C99 compiler.  With -pedantic, it tells
  you that "anonymous unions are a C11 extension [-Wc11-extensions]".

- anonymous unions are actually a gnu99 extension.  But is closer to
  resembling a C99 compiler when requested to be one.  It doesn't take
  -pedantic to make it warn about anonymous unions in the kernel.

- you "fixed" this for gcc in r278913 by adding -fms-extensions for gcc
  only.  This is in kern.pre.mk and kmod.mk.  MS apparently added this
  extension 10-20 years after gnu added it.  -fms-extensions gives
  subtly different (mostly stronger) semantics for anonymous unions.
  The kernel only needs old gnu semantics.  -ms-extensions gives many
  other unwanted NS extensions.  -current still has this bug.

- r338128 adds -ms-extensions to CFLAGS for gcc on a different line.  This
  bug is missing in kmod.mk.  -current still has this bug.

Nearby bugs:

- -fms-extensions was added in a wrong place in r278913.  It was added after
  -fno-common, which was already in a wrong place.  In FreeBSD-7, -fno-common
  was added before inline limits, but on the same line as the first inline
  limit.  Inline limits are very gcc-4.2.1-specific, so they needed ifdefs.
  There are now some ifdefs.  Not nearly enough -- only 1 for mips and ones
  for gcc implemented using CFLAGS.gcc.

  The bug is now -fno-common is ifdefed for gcc using CFLAGS.gcc, so it is
  broken for clang (in FreeBSD-7, it was ifdefed for icc using an explicit
  ifdef.

- I once fixed large parts of the kernel (at least all header files) to
  compile with -pedantic.  The fixes included marking extensions using
  __extension__, expecially in header files.  -pedantic is unusuable now
  even 1 file at a time, due to too many syntax errors and unmarked
  extensions in headers.  E.g., compiling init_main.c now gives 2345
  errors in 17312 lines after increasing -ferror-limit from 20 to 100.
  With the default limit of 20, the following errors are detected:

XX In file included from ../../../kern/init_main.c:55:
XX In file included from ../../../sys/epoch.h:41:
XX In file included from ../../../sys/pcpu.h:50:
XX ./machine/pcpu.h:49:1: error: _Static_assert is a C11-specific feature 
[-Werror,-Wc11-extensions]
XX _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line");
XX ^
XX In file included from ../../../kern/init_main.c:56:
XX In file included 

Re: svn commit: r347984 - in head/sys: amd64/vmm/io arm/allwinner arm/allwinner/a10 arm/allwinner/clkng arm/arm arm/broadcom/bcm2835 arm/freescale/imx arm/mv arm/mv/armada arm/nvidia arm/nvidia/tegra1

2019-05-20 Thread Bruce Evans

On Mon, 20 May 2019, Conrad Meyer wrote:


Log:
 Extract eventfilter declarations to sys/_eventfilter.h


sys/_eventhandler.h has 2 identical 72-line copies of the correct version.
The second copy of the reinclusion guard works as a guard against the
doubling too.



 This allows replacing "sys/eventfilter.h" includes with "sys/_eventfilter.h"
 in other header files (e.g., sys/{bus,conf,cpu}.h) and reduces header
 pollution substantially.

 EVENTHANDLER_DECLARE and EVENTHANDLER_LIST_DECLAREs were moved out of .c
 files into appropriate headers (e.g., sys/proc.h, powernv/opal.h).


Thanks, but this gives even more pollution.  Almost everything includes
sys/proc.h, so its already large pollution affects almost everything.
The previous pollution in it didn't include sys/eventhandler.h, except
possibly via a nested include.


Modified: head/sys/amd64/vmm/io/iommu.c
==
--- head/sys/amd64/vmm/io/iommu.c   Sun May 19 23:56:04 2019
(r347983)
+++ head/sys/amd64/vmm/io/iommu.c   Mon May 20 00:38:23 2019
(r347984)
@@ -32,10 +32,10 @@
__FBSDID("$FreeBSD$");

#include 
-#include 
-#include 


Error.  sys/systm.h must be included after sys/param.h, since it contains
macros like KASSERT() which may be used in inline functions in any kernel
header except sys/param.h and possibly sys/types.h.


Modified: head/sys/arm/allwinner/a10/a10_intc.c
==
--- head/sys/arm/allwinner/a10/a10_intc.c   Sun May 19 23:56:04 2019
(r347983)
+++ head/sys/arm/allwinner/a10/a10_intc.c   Mon May 20 00:38:23 2019
(r347984)
@@ -30,11 +30,12 @@ __FBSDID("$FreeBSD$");

#include "opt_platform.h"

-#include 
+#include 


Including sys/types.h and not including sys/param.h was another error.
sys/param.h supplies lots of standard pollution that may be depended
on by any other kernel header.  It is impractical to even test if
sys/types.h works with all combinations of ifdefs.


#include 
#include 
#include 
#include 
+#include 
#include 
#include 
#include 


sys/param.h is now included twice.  It is another header that must be
included in non-alphabetical order.  The second include may have
compensated for not including it first.



Modified: head/sys/arm/allwinner/a10_dmac.c
==
--- head/sys/arm/allwinner/a10_dmac.c   Sun May 19 23:56:04 2019
(r347983)
+++ head/sys/arm/allwinner/a10_dmac.c   Mon May 20 00:38:23 2019
(r347984)
@@ -38,7 +38,9 @@ __FBSDID("$FreeBSD$");
#include 
#include 
#include 
+#include 
#include 
+#include 

#include 

Modified: head/sys/arm/allwinner/a31_dmac.c
==
--- head/sys/arm/allwinner/a31_dmac.c   Sun May 19 23:56:04 2019
(r347983)
+++ head/sys/arm/allwinner/a31_dmac.c   Mon May 20 00:38:23 2019
(r347984)
@@ -38,7 +38,9 @@ __FBSDID("$FreeBSD$");
#include 
#include 
#include 
+#include 
#include 
+#include 
#include 

#include 


I gave up trying to fix missing includes of sys/mutex.h and its
prerequisite sys/lock.h 15+ years ago before disk code added lots more
of them.  sys/buf.h was polluted by adding an include of sys/mutex.h,
and most disk drivers dependended on that.  The only other includes
of sys/mutex.h in a  header were in sys/eventhandler.h and
sys/vnode.h, and the latter was fixed in my version.  This pollution
has spread to sys/buf_ring.h, sys/fail.h, sys/jail.h, sys/mman.h,
sys/msgbuf.h, sys/rmlock.h, sys/timeet.h and sys/tty.h.

The smaller headers here are trivial to fix, and even sys/vnode.h
wasn't hard to fix 15 years ago before the pollution spread.  sys/mman.h
seems to have only 1 mutex declaration, of a struct mtx, so using the
correct header sys/_mutex.h works.  Only inlines using mutexes cause
pollution that is hard to avoid.  sys/vnode.h still has only 1 inline
function.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r347951 - stable/12/lib/libc/stdlib

2019-05-20 Thread Bruce Evans

On Sun, 19 May 2019, Warner Losh wrote:


On Sun, May 19, 2019 at 9:56 AM Yoshihiro Ota  wrote:


I wonder if we can use a tool to confirm coding style like
clang-format or something else.


I don't know... it might be hard to do that inside a man page...


Examples in man pages need special treatment since man adds a 5 column
left margin and then must mangle tabs to preserve 8-column indentation.
The examples must at least be formatted for width 74 instead of 79, but
74 is better anyway.

I had some success turning SYNOPSIS sections into C code for checking
that the headers are complete and the documented prototypes agree with
the headers.  Large examples would probably have to be extracted manually
since they are less structured than SYNOPSIS sections.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r347953 - head/cddl/contrib/opensolaris/cmd/zfs

2019-05-18 Thread Bruce Evans

On Sat, 18 May 2019, Toomas Soome wrote:


On 18 May 2019, at 15:37, Alexey Dokuchaev  wrote:

On Sat, May 18, 2019 at 12:27:22PM +, Allan Jude wrote:

New Revision: 347953
URL: https://svnweb.freebsd.org/changeset/base/347953

Log:
 MFV/ZoL: `zfs userspace` ignored all unresolved UIDs after the first

 zfsonlinux/zfs@88cfff182432e4d1c24c877f33b47ee6cf109eee

 zfs_main: fix `zfs userspace` squashing unresolved entries

...
@@ -2368,10 +2369,12 @@ us_compare(const void *larg, const void *rarg, void *u
if (rv64 != lv64)
rc = (rv64 < lv64) ? 1 : -1;
} else {
-   (void) nvlist_lookup_string(lnvl, propname,
-   );
-   (void) nvlist_lookup_string(rnvl, propname,
-   );
+   if ((nvlist_lookup_string(lnvl, propname,
+   ) == ENOENT) ||
+   (nvlist_lookup_string(rnvl, propname,
+   ) == ENOENT)) {
+   goto compare_nums;
+   }


Another thing not to like about ZoL: their completely bogus code style
and formatting practices (look at those ") == ENOENT").  If they
are going to listen to us, can we at least try to convince them not to
break existing, much FreeBSD-like formatting?


Actually it is required to use the proper cstyle??? 
https://github.com/zfsonlinux/zfs/blob/master/.github/CONTRIBUTING.md#style-guides 


Therefore bogus style is bug.


Indeed, the change was away from the proper cstyle.

Old zfs code is closer to KNF than most FreeBSD code, perhaps because
its cstyle guide is better than style(9) and is actually followed.  It
requires 4-space continuation indents the same as KNF, but these were
broken in the patch.  It requires casts to not be followed by a blank
(i.e., space), except, unfortunately, for function calls whose return
values are ignored.  So the old code above conformed to cstyle but not
to style(9) since it has spaces after "(void)" but otherwise conforms
to KNF.

The cstyle pdf in the above url was written in 1993 and last updated
in 1996.  Its age would be a feature, except it has only primitive
support for C90 (it never mentions "prototype" or ISO C, but has a
couple of examples of "ANSI" function definitions).  So it isn't
actually better than style(9), and I doubt that anyone actually follows
all of it.  Especially its requirement to support K in headers and its
examples of incomplete K declarations.

Bruce___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r347951 - stable/12/lib/libc/stdlib

2019-05-18 Thread Bruce Evans

On Sat, 18 May 2019, Konstantin Belousov wrote:


On Sat, May 18, 2019 at 03:15:08AM +, Benedict Reuschling wrote:

Author: bcr (doc committer)
Date: Sat May 18 03:15:07 2019
New Revision: 347951
URL: https://svnweb.freebsd.org/changeset/base/347951

Log:
  MFC r347617:
  Add small EXAMPLE section to bsearch.3.

  Submitted by: fernape (via Phabricator)
  Reviewed by:  bcr, jilles, dab
  Approved by:  bcr (man pages), jilles (src)
  Differential Revision:https://reviews.freebsd.org/D19902

Modified:
  stable/12/lib/libc/stdlib/bsearch.3
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/lib/libc/stdlib/bsearch.3
==
--- stable/12/lib/libc/stdlib/bsearch.3 Sat May 18 02:02:14 2019
(r347950)
+++ stable/12/lib/libc/stdlib/bsearch.3 Sat May 18 03:15:07 2019
(r347951)
@@ -32,7 +32,7 @@
 .\" @(#)bsearch.3 8.3 (Berkeley) 4/19/94
 .\" $FreeBSD$
 .\"
-.Dd February 22, 2013
+.Dd May 15, 2019
 .Dt BSEARCH 3
 .Os
 .Sh NAME
@@ -83,6 +83,61 @@ The
 function returns a pointer to a matching member of the array, or a null
 pointer if no match is found.
 If two members compare as equal, which member is matched is unspecified.
+.Sh EXAMPLES
+A sample program that searches people by age in a sorted array:
+.Bd -literal
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct person {
+   char name[5];
+   int age;
+};


This example has a high density of style bugs.  kib pointed out some.
Some of the others are:

(1) Not sorting the struct members on alignment.  (style(9) says to sort
on use, then size, but means alignment).
(2) Not indenting the struct member names.
(3) Not use a prefix for struct member names.  This is not important for
small programs.


+
+int
+compare(const void *key, const void *array_member)
+{
+   int age = (intptr_t) key;
+   struct person person = *(struct person *) array_member;

These two lines contain at least three style(9) bugs, and at least one
warning at higher warning level.


+
+   return (age - person.age);
+}
+
+int
+main()

Why use K definition ?


+{
+   struct person *friend;
+
+   /* Sorted array */
+   struct person friends[6] = {
+   { "paul", 22 },
+   { "anne", 25 },
+   { "fred", 25 },
+   { "mary", 27 },
+   { "mark", 35 },
+   { "bill", 50 }
+   };
+
+   size_t array_size = sizeof(friends) / sizeof(struct person);

Since you used const elsewere, why did not you used it there ?


(4) The size expression is obfuscated by spelling the element size as
sizeof(struct person) instead of sizeof(friends[0]).
(5?) FreeBSD now spells this size expression as nitems(friends).  I don't
like the unportability of this, especially in an example.




+
+   friend = bsearch((void *)22, , array_size, sizeof(struct 
person), compare);

Taking address of an array is weird.
Line is too long.


(6) C99 specifies that the search is for a member of the array that matches
the object pointed to by 'key'.  Here the key of (void *)22 is a
not a pointer to an object.  It is a cookie which points to garbage.
The cookie is unique enough to work in practice.  Perhaps you can
prove it to always work if the option type intptr_t is supported.
But this is a bad example.
(4a) same obfuscation of the element size.




+   assert(strcmp(friend->name, "paul") == 0);
+   printf("name: %s\enage: %d\en", friend->name, friend->age);
+


(7) Extra blank line.  This is not too bad, but is not done consistently.


+   friend = bsearch((void *)25, , array_size, sizeof(struct 
person), compare);


(8) More too-long lines.
(4b) More sizeof(person)'s.


+   assert(strcmp(friend->name, "fred") == 0 || strcmp(friend->name, 
"anne") == 0);


(7a) No extra blank line for "fred".


+   printf("name: %s\enage: %d\en", friend->name, friend->age);
+
+   friend = bsearch((void *)30, , array_size, sizeof(struct 
person), compare);
+   assert(friend == NULL);
+   printf("friend aged 30 not found\en");


I didn't notice before that the key cookie was an encoding of the age.

The key is not unique (there are 2 25's).  This gives an example of low
quality data and the example has minimal error handling handling for this
without describing what it is doing (it asserts uniqueness for age 22 and
it asserts one of the 2 possibilities for age 25.  It can only do this
because it knows too much about the data).

It is more than a style bug to handle errors in data by assert() or
otherwise killing the program, except possibly when the data is supposed
to be good.


+
+   return (EXIT_SUCCESS);
+}
+.Ed
 .Sh SEE ALSO
 .Xr db 3 ,
 .Xr lsearch 3 ,


Bruce
___
svn-src-all@freebsd.org mailing list

Re: svn commit: r347484 - head/sys/kern

2019-05-12 Thread Bruce Evans

On Sat, 11 May 2019, Doug Moore wrote:


On 5/11/19 5:52 AM, Bruce Evans wrote:

On Sat, 11 May 2019, Doug Moore wrote:

+#ifdef HAVE_INLINE_FFS
+?? case sizeof(int):
+?? return (ffs(mask) - 1);
+#endif


This is unreachable, since sizeof(int) is 4 on all supported arches, and
sizeof(mask) is 8 on all arches.


Another FreeBSD developer has expressed to me that sizeof(mask) ought to
become 4 on some 32-bit arches before too long, and I added this case in
anticipation of that.?? I see now that I should have waited.


I also don't like the use of unsigned long for __fd_mask and bitstr_t.
This asks for a a pessimal type that is twice as wide as a machine
register, but is not so pessimal in practice since longs are rarely
implemented correctly except on systems with 16-bit machine registers.

The mask type u_daddr_t is both logically wrong (masks have nothing to
do with daddr_t's) and gives a pessimal bitstring type more often in
practice:
- in FreeBSD-4, [u_]daddr_t was 32 bits, so misusing it for bitstrings
  was pessimal on 64-bit arches
- expanding [u_]daddr_t to 64 bits in FreeBSD-5 (r96572-96851 only 17
  years ago) made it pessimal for bitstrings on 32-bit arches.

The pessimization would be smaller if ffs64() exists and is inlined to
32-bit ffs()'s.

Using the long long abomination asks for double the pessimizations and
machine dependencies as using long.  In practice, expanding long long
to larger than 64 bits would break ABIs so it is not much worse than
a spelling error for int64_t.

Bruce___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r347484 - head/sys/kern

2019-05-11 Thread Bruce Evans

On Sat, 11 May 2019, Doug Moore wrote:


Log:
 When bitpos can't be implemented with an inline ffs* instruction,
 change the binary search so that it does not depend on a single bit
 only being set in the bitmask. Use bitpos more generally, and avoid
 some clearing of bits to accommodate its current behavior.


Inline ffs*() is badly implemented in general (it is mostly not implemented
in the kernel).  This makes it almost useless here, and (non-inline) ffs*()
(not used here) often slower than direct methods.


Modified: head/sys/kern/subr_blist.c
==
--- head/sys/kern/subr_blist.c  Sat May 11 04:18:06 2019(r347483)
+++ head/sys/kern/subr_blist.c  Sat May 11 09:09:10 2019(r347484)
...
+static inline int
+bitpos(u_daddr_t mask)
+{
+
switch (sizeof(mask)) {
#ifdef HAVE_INLINE_FFSLL
case sizeof(long long):
return (ffsll(mask) - 1);
#endif


This uses the long long abomination.  Only amd64 has inline ffsll().


+#ifdef HAVE_INLINE_FFS
+   case sizeof(int):
+   return (ffs(mask) - 1);
+#endif


This is unreachable, since sizeof(int) is 4 on all supported arches, and
sizeof(mask) is 8 on all arches.


default:
-   lo = 0;
-   hi = BLIST_BMAP_RADIX;
-   while (lo + 1 < hi) {
-   mid = (lo + hi) >> 1;
-   if ((mask >> mid) != 0)
-   lo = mid;
-   else
-   hi = mid;
-   }
-   return (lo);
+   return (generic_bitpos(mask));
}
}


So the default cause is used except on amd64.  I think the direct code
for it is not as slow as the generic (libkern) ffs*(), except the generic
ffs*() is simpler so the compiler might inline it internals to
__builtin_ffs*().  Not that -ffreestanding prevents inlining extern ffs*().

Since 64/8 is 2 times 4 and sizeof(int) >= 4 in POSIX, it is trivial to
implement ffs64() using 2 inline ffs()'s, and that is exactly what clang
does on i386 to implement __builtin_ffsl().  Unfortunately, most arches
also don't implement inline ffs().  Only amd64, i386 and sparc64 implement
it.

subr_blist.c is also complilable outside of the kernel.  I don't like that.
The kernel macros HAVE_INLINE_* don't exist outside of the kernel, but
ffs*() would work better outside of the kernel if it is used blindly since
inlining of it isn't prevented by -ffreestanding.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r347063 - head/sys/kern

2019-05-07 Thread Bruce Evans

On Tue, 7 May 2019, John Baldwin wrote:


On 5/7/19 8:45 AM, Bruce Evans wrote:

On Mon, 6 May 2019, John Baldwin wrote:


On 5/6/19 11:45 AM, Mark Johnston wrote:

On Mon, May 06, 2019 at 11:07:18AM -0700, John Baldwin wrote:

On 5/3/19 2:26 PM, Mark Johnston wrote:

Author: markj
Date: Fri May  3 21:26:44 2019
New Revision: 347063
URL: https://svnweb.freebsd.org/changeset/base/347063

Log:
  Disallow excessively small times of day in clock_settime(2).


This actually disallows negative timespecs in clock_settime(), with
collateral disallowment for small positive times.


FWIW, clock_settime already disallows negative times due to the
existing check in the previous two lines:

if (ats->tv_nsec < 0 || ats->tv_nsec >= 10 ||
ats->tv_sec < 0)
return (EINVAL);

I would probably lean towards not disallowing negative times as I
said in one of my earlier replies, but given we have that blanket
check already in place, the current patch doesn't seem to make
things much worse.


This check was correctly missing in FreeBSD-5.

This check doesn't actually work.  I rememeber another detail in my test
program.  It sets the time to INT_MAX - 2 == INT32_MAX - 2 to get an
overflow 2 seconds later with 32-bit time_t.  This is how I got a file
time of 1901.

The check for large times on the line after the above is broken in another
way.  It has an upper limit of approx. 8000ULL years.  This limit is
unreachable for 32-bit time_t (except for the unsign extension bug for
negative times which is unreachable due to the above check).  So the check
only works to prevent overflow to a negative time with 64-bit time_t.

Other parts of the system are or were more careful about this:
- setitimer() and alarm() used to have a limit of 10**8 seconds to
  prevent overflow of 32-bit time_t when adding this number to the
  current time.  10**8 seconds is 3.16 years, so this works up to about
  2035.  This was broken by silently removing the check for 10**8 in
  itimerfix() as part of implementing POSIX itimers but the man pages
  still document the limit.  This is not allowed by POSIX.  POSIX
  requires times to work up to the limit of a time_t.  Some APIs return
  the residual time after a timeout, so this cannot be implemented by
  clamping the time to a reasonably small value.  POSIX itimers have a
  different implementation that is closer to not needing this limit
  and more broken having it.

  setitimer() is also broken for negative times (doesn't allow them).
  IIRC, POSIX requires this bug.  This just give more work for applications.
  Small negative differences can easily occur as the result of subtracting
  times.  Applications must either check for them after calculating
  differences, or handle the error for them from setimer().  Usually the
  correct handling is to treat negative timeouts as 0.

- sbintimes have 32 bits for the seconds part, so they have similar
  problems to 32-bit time_t.  Some places handle these problems by limiting
  the timeouts to INT32_MAX / 2.  The timeout is sometimes added to the
  current time, but since the current time is the monotonic time it is at
  most a few years so the limit for the timeout could be a bit larger than
  INT32_MAX / 2.

Oops, sbintimes are now used for for setitimer(), and setitimer() is one
of the few places with the INT32_MAX / 2 limit.  This gives the following
bugs for setitimer() and alarm():
- these syscalls still have a limit which is not allowed by POSIX
- the limit is INT32_MAX / 2 seconds (+ maximal usec?), not the documented
  one.

64_bit time_t's mostly just increase the overflow bugs.  Applications can
probe for bugs using INT64_MAX in tv_sec.  This overflows all 32-bit
calculations and most signed 64-bit calculations.  The kernel has to
reduce to 32 bits in seconds for all uses of sbintimes.  The kernel
does do this for nanosleep().

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r347063 - head/sys/kern

2019-05-07 Thread Bruce Evans

On Mon, 6 May 2019, John Baldwin wrote:


On 5/6/19 11:45 AM, Mark Johnston wrote:

On Mon, May 06, 2019 at 11:07:18AM -0700, John Baldwin wrote:

On 5/3/19 2:26 PM, Mark Johnston wrote:

Author: markj
Date: Fri May  3 21:26:44 2019
New Revision: 347063
URL: https://svnweb.freebsd.org/changeset/base/347063

Log:
  Disallow excessively small times of day in clock_settime(2).


This actually disallows negative timespecs in clock_settime(), with
collateral disallowment for small positive times.

I don't like disallowing either.  The bounds checking in the clock code
is badly implemented, so it crashes on such times even if the clock
hardware supports them, but clock_settime() is privileged and root never
makes mistakes.

This breaks:
- testing of setting negative times
- my enclosed test to demonstrate bugs in the bounds checking.



  Reported by:  syzkaller
  Reviewed by:  cem, kib
  MFC after:1 week
  Sponsored by: The FreeBSD Foundation
  Differential Revision:https://reviews.freebsd.org/D20151

Modified:
  head/sys/kern/kern_time.c

Modified: head/sys/kern/kern_time.c
==
--- head/sys/kern/kern_time.c   Fri May  3 21:13:09 2019(r347062)
+++ head/sys/kern/kern_time.c   Fri May  3 21:26:44 2019(r347063)
@@ -412,7 +412,9 @@ kern_clock_settime(struct thread *td, clockid_t clock_
if (ats->tv_nsec < 0 || ats->tv_nsec >= 10 ||
ats->tv_sec < 0)
return (EINVAL);
-   if (!allow_insane_settime && ats->tv_sec > 8000ULL * 365 * 24 * 60 * 60)
+   if (!allow_insane_settime &&
+   (ats->tv_sec > 8000ULL * 365 * 24 * 60 * 60 ||
+   ats->tv_sec < utc_offset()))
return (EINVAL);


The test of the upper bound is broken.  It not only uses the long long
abomination, but uses large unsigned type which gives unsigned
poisoning for all supported sizes of time_t.  So negative times were
already broken here (without allow_insane_settime).  They are converted
to large positive times so are treated as insanely large.

utc_offset() uses a too-small signed type with no bounds checking so it
has overflow bugs but doesn't give unsigned poisoning.

time_t is signed on all supported arches.  It could be uint32_t so as to
work until 2106 on 32-bit arches, but this would give unsigned poisoning
and there is too much broken code for changing it to that to just work.

So the new code doesn't have unsigned poisoning, and it disallows most
negative values even when utc_offset() is negative.


/* XXX Don't convert nsec->usec and back */
TIMESPEC_TO_TIMEVAL(, ats);


Pardon my ignorance, but I can't see why you are checking against utc_offset()
vs some small constant?  None of the discussion in the review mentioned the
reason for using this particular value, and I didn't see any comparisons
against utc_offset or kernadjtz in kern_clock_setttime() or settime() that
would have underflowed or panicked.  Can you give a bit more detail on why
utc_offset() is the lower bound?  Thanks.


I chose it because we subtract utc_offset() from the time passed in to
clock_settime(); see settime_task_func().  That subtraction caused the
underflow that later caused the observed panics.


Not underflow, but overflow.  Underflow is when rounding a small nonzero
floating point value gives a denormal value of 0.

This was the main overflow bug demonstrated by my test program.


Ok, thanks.  A few things I didn't see anyone else note in the review then:

1) This subtraction is actually not done for all rtc drivers, so it seems
  like we might block small times for RTC clocks that set
  CLOCKF_GETTIME_NO_ADJ.


It is probably bogus to check it for them.  The check is misplaced for them
-- this level can't know the details.


2) utc_offset can be negative for machines using local time in timezones
  "before" UTC.


This is why it is less bad to check utc_offset() than 0.  Otherwise, it
would be impossible to test setting the time to the Epoch in these timezones.

Hmm, the offset is confusing, especially its sign.  In these timezones,
when the time is the Epoch, the local time is before the Epoch so the RTC
hardware needs to be able to represent year 1969 even if utc_offset() is
sane.  But some clock drivers convery 1969 to 2069, and the sanity check
in clock_ct_to_ts() is insane -- it doesn't allow years before 1970,
although signed time_t has no problems before year 1901.  So testing of
setting the time to the Epoch in such timezones would show that even if
the RTC can be set to 1969, the kernel time can't be restored to the
Epoch from the RTC.

I don't know of any panics from buggy bounds checks for this.  The worst
that can happen is that adjkerntz is preposterous.  Then utc_offset() is
preposterous and adding it can change a 32-bit time_t to anything and a
64-bit time_t by a lot


I suppose we don't think any FreeBSD machines actually need to set the
running clock 

svn commit: r347054 - head/lib/libvgl

2019-05-03 Thread Bruce Evans
Author: bde
Date: Fri May  3 13:06:46 2019
New Revision: 347054
URL: https://svnweb.freebsd.org/changeset/base/347054

Log:
  Fix copying planar bitmaps when the horizontal start and end are both not
  multiples of 8.  Then the misaligned pixels at the end were not copied.
  
  Clean up variable misuse related to this bug.  The width in bytes was
  first calculated correctly and used to do complicated reblocking
  correctly, but it was stored in an unrelated scratch variable and later
  recalculated with an off-by-1-error, so the last byte (times 4 planes)
  in the intermediate copy was not copied.
  
  This doubly-misaligned case is especially slow.  Misalignment complicates
  the reblocking, and each misaligment requires a read before write, and this
  read is still not done from the shadow buffer.

Modified:
  head/lib/libvgl/bitmap.c

Modified: head/lib/libvgl/bitmap.c
==
--- head/lib/libvgl/bitmap.cFri May  3 09:38:23 2019(r347053)
+++ head/lib/libvgl/bitmap.cFri May  3 13:06:46 2019(r347054)
@@ -47,7 +47,7 @@ static int color2bit[16] = {0x, 0x0001, 0x
 static void
 WriteVerticalLine(VGLBitmap *dst, int x, int y, int width, byte *line)
 {
-  int i, pos, last, planepos, start_offset, end_offset, offset;
+  int bwidth, i, pos, last, planepos, start_offset, end_offset, offset;
   int len;
   unsigned int word = 0;
   byte *address;
@@ -58,13 +58,13 @@ WriteVerticalLine(VGLBitmap *dst, int x, int y, int wi
   case VIDBUF4S:
 start_offset = (x & 0x07);
 end_offset = (x + width) & 0x07;
-i = (width + start_offset) / 8;
+bwidth = (width + start_offset) / 8;
 if (end_offset)
-   i++;
+   bwidth++;
 VGLPlane[0] = VGLBuf;
-VGLPlane[1] = VGLPlane[0] + i;
-VGLPlane[2] = VGLPlane[1] + i;
-VGLPlane[3] = VGLPlane[2] + i;
+VGLPlane[1] = VGLPlane[0] + bwidth;
+VGLPlane[2] = VGLPlane[1] + bwidth;
+VGLPlane[3] = VGLPlane[2] + bwidth;
 pos = 0;
 planepos = 0;
 last = 8 - start_offset;
@@ -87,9 +87,6 @@ WriteVerticalLine(VGLBitmap *dst, int x, int y, int wi
   VGLPlane[2][planepos] = word>>16;
   VGLPlane[3][planepos] = word>>24;
 }
-if (start_offset || end_offset)
-  width+=8;
-width /= 8;
 outb(0x3ce, 0x01); outb(0x3cf, 0x00);  /* set/reset enable */
 outb(0x3ce, 0x08); outb(0x3cf, 0xff);  /* bit mask */
 for (i=0; i<4; i++) {
@@ -103,7 +100,7 @@ WriteVerticalLine(VGLBitmap *dst, int x, int y, int wi
  VGLPlane[i][planepos] |= dst->Bitmap[pos+planepos] & mask[end_offset];
if (start_offset)
  VGLPlane[i][0] |= dst->Bitmap[pos] & ~mask[start_offset];
-   bcopy([i][0], dst->Bitmap + pos, width);
+   bcopy([i][0], dst->Bitmap + pos, bwidth);
   } else { /* VIDBUF4S */
if (end_offset) {
  offset = VGLSetSegment(pos + planepos);
@@ -112,9 +109,9 @@ WriteVerticalLine(VGLBitmap *dst, int x, int y, int wi
offset = VGLSetSegment(pos);
if (start_offset)
  VGLPlane[i][0] |= dst->Bitmap[offset] & ~mask[start_offset];
-   for (last = width; ; ) { 
+   for (last = bwidth; ; ) { 
  len = min(VGLAdpInfo.va_window_size - offset, last);
- bcopy([i][width - last], dst->Bitmap + offset, len);
+ bcopy([i][bwidth - last], dst->Bitmap + offset, len);
  pos += len;
  last -= len;
  if (last <= 0)
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346895 - head/lib/libvgl

2019-04-29 Thread Bruce Evans
Author: bde
Date: Mon Apr 29 16:26:29 2019
New Revision: 346895
URL: https://svnweb.freebsd.org/changeset/base/346895

Log:
  Support all reasonable cursor sizes.  Reduce the size of the standard
  cursor from 16x16 (with 6 columns unused) to 10x16 and rename it to
  the "small" cursor.  Add a "large" 19x32 cursor and use it for screen
  widths larger than 800 pixels.  Use libvgl's too-small indentation for
  the large data declarations.
  
  MOUSE_IMG_SIZE = 16 is still part of the API.  If an application supplies
  invalid bitmaps for the cursor, then the results may be different from
  before.

Modified:
  head/lib/libvgl/mouse.c

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Mon Apr 29 16:24:51 2019(r346894)
+++ head/lib/libvgl/mouse.c Mon Apr 29 16:26:29 2019(r346895)
@@ -43,52 +43,132 @@ static void VGLMouseAction(int dummy);
 
 #define BORDER 0xff/* default border -- light white in rgb 3:3:2 */
 #define INTERIOR 0xa0  /* default interior -- red in rgb 3:3:2 */
+#define LARGE_MOUSE_IMG_XSIZE  19
+#define LARGE_MOUSE_IMG_YSIZE  32
+#define SMALL_MOUSE_IMG_XSIZE  10
+#define SMALL_MOUSE_IMG_YSIZE  16
 #define X  0xff/* any nonzero in And mask means part of cursor */
 #define B  BORDER
 #define I  INTERIOR
-static byte StdAndMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
-   X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
-   X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
-   X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,
-   X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
-   X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,
-   X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
-   X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,
-   X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,
-   X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
-   X,X,X,0,X,X,X,X,0,0,0,0,0,0,0,0,
-   X,X,0,0,X,X,X,X,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,
-   0,0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,
-   0,0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,
+static byte LargeAndMask[] = {
+  X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
+  X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
+  X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,
+  X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
+  X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,
+  X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
+  X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,
+  X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,
+  X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,
+  X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,
+  X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,
+  X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,
+  X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+  X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+  X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
+  X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
+  X,X,X,X,X,X,0,X,X,X,X,X,X,0,0,0,0,0,0,
+  X,X,X,X,X,0,0,X,X,X,X,X,X,0,0,0,0,0,0,
+  X,X,X,X,0,0,0,0,X,X,X,X,X,X,0,0,0,0,0,
+  X,X,X,0,0,0,0,0,X,X,X,X,X,X,0,0,0,0,0,
+  X,X,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,X,X,X,X,0,0,0,
 };
-static byte StdOrMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
-   B,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   B,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   B,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,
-   B,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,
-   B,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,
-   B,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,
-   B,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,
-   B,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,
-   B,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,
-   B,I,I,I,I,I,B,B,B,B,0,0,0,0,0,0,
-   B,I,I,B,I,I,B,0,0,0,0,0,0,0,0,0,
-   B,I,B,0,B,I,I,B,0,0,0,0,0,0,0,0,
-   B,B,0,0,B,I,I,B,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,B,I,I,B,0,0,0,0,0,0,0,
-   0,0,0,0,0,B,I,I,B,0,0,0,0,0,0,0,
-   0,0,0,0,0,0,B,B,0,0,0,0,0,0,0,0,
+static byte LargeOrMask[] = {
+  B,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  B,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  B,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  B,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  B,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  B,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,
+  B,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,
+  B,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,
+  B,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,
+  B,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,
+  B,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,
+  B,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,
+  B,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,
+  B,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,
+  B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,
+  B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,
+  B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,
+  B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,
+  

svn commit: r346890 - head/lib/libvgl

2019-04-29 Thread Bruce Evans
Author: bde
Date: Mon Apr 29 15:58:05 2019
New Revision: 346890
URL: https://svnweb.freebsd.org/changeset/base/346890

Log:
  Oops, r346889 broke showing of the mouse cursor after clearing, by
  forgetting to tell the bitmap-copying clearing method to preserve the
  cursor.

Modified:
  head/lib/libvgl/simple.c

Modified: head/lib/libvgl/simple.c
==
--- head/lib/libvgl/simple.cMon Apr 29 14:13:53 2019(r346889)
+++ head/lib/libvgl/simple.cMon Apr 29 15:58:05 2019(r346890)
@@ -496,7 +496,7 @@ VGLClear(VGLBitmap *object, u_long color)
 for (i = 0; i < object->VXsize; i++)
   bcopy(, src.Bitmap + i * object->PixelBytes, object->PixelBytes);
 for (i = 0; i < object->VYsize; i++)
-  __VGLBitmapCopy(, 0, 0, object, 0, i, object->VXsize, 1);
+  __VGLBitmapCopy(, 0, 0, object, 0, i, object->VXsize, -1);
 break;
 
   case VIDBUF8X:
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346889 - head/lib/libvgl

2019-04-29 Thread Bruce Evans
Author: bde
Date: Mon Apr 29 14:13:53 2019
New Revision: 346889
URL: https://svnweb.freebsd.org/changeset/base/346889

Log:
  Refactor and simplify hiding the mouse cursor and fix bugs caused by
  complications in the previous methods.
  
  r346761 broke showing the mouse cursor after changing its state from
  off to on (including initially), since showing the cursor uses the
  state to decide whether to actually show and the state variable was
  not changed until after null showing.  Moving the mouse or copying
  under the cursor fixed the problem.  Fix this and similar problems for
  the on to off transition by changing the state variable before drawing
  the cursor.
  
  r346641 failed to turn off the mouse cursor on exit from vgl.  It hid
  the cursor only temporarily for clearing.  This doesn't change the state
  variable, so unhiding the cursor after clearing restored the cursor if its
  state was on.  Fix this by changing its state to VGL_MOUSEHIDE using the
  application API for changing the state.
  
  Remove the VGLMouseVisible state variable and the extra states given by it.
  This was an optimization that was just an obfuscation in at least the
  previous version.
  
  Staticize VGLMouseAction().  Remove VGLMousePointerShow/Hide() except as
  internals in __VGLMouseMode().  __VGLMouseMouseMode() is the same as the
  application API VGLMouseMouseMode() except it returns the previous mode
  which callers need to know to restore it after hiding the cursor.
  
  Use the refactoring to make minor improvements in a simpler way than was
  possible:
  - in VGLMouseAction(), only hide and and unhide the mouse cursor if the
mouse moved
  - in VGLClear(), only hide and and unhide the mouse cursor if the clearing
method would otherwise clear the cursor.

Modified:
  head/lib/libvgl/main.c
  head/lib/libvgl/mouse.c
  head/lib/libvgl/simple.c
  head/lib/libvgl/vgl.h

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Mon Apr 29 13:23:32 2019(r346888)
+++ head/lib/libvgl/main.c  Mon Apr 29 14:13:53 2019(r346889)
@@ -77,7 +77,7 @@ struct vt_mode smode;
   signal(SIGUSR2, SIG_IGN);
   VGLSwitchPending = 0;
   VGLAbortPending = 0;
-  VGLMousePointerHide();
+  VGLMouseMode(VGL_MOUSEHIDE);
 
   if (VGLMem != MAP_FAILED) {
 VGLClear(VGLDisplay, 0);

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Mon Apr 29 13:23:32 2019(r346888)
+++ head/lib/libvgl/mouse.c Mon Apr 29 14:13:53 2019(r346889)
@@ -39,6 +39,8 @@ __FBSDID("$FreeBSD$");
 #include 
 #include "vgl.h"
 
+static void VGLMouseAction(int dummy);
+
 #define BORDER 0xff/* default border -- light white in rgb 3:3:2 */
 #define INTERIOR 0xa0  /* default interior -- red in rgb 3:3:2 */
 #define X  0xff/* any nonzero in And mask means part of cursor */
@@ -88,7 +90,6 @@ static VGLBitmap VGLMouseStdAndMask = 
 static VGLBitmap VGLMouseStdOrMask = 
 VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdOrMask);
 static VGLBitmap *VGLMouseAndMask, *VGLMouseOrMask;
-static int VGLMouseVisible = 0;
 static int VGLMouseShown = VGL_MOUSEHIDE;
 static int VGLMouseXpos = 0;
 static int VGLMouseYpos = 0;
@@ -102,51 +103,44 @@ static volatile sig_atomic_t VGLMsuppressint;
VGLMouseAction(0);  \
} while (0)
 
-void
-VGLMousePointerShow()
+int
+__VGLMouseMode(int mode)
 {
-  if (!VGLMouseVisible) {
-INTOFF();
-VGLMouseVisible = 1;
-__VGLBitmapCopy(, VGLMouseXpos, VGLMouseYpos, VGLDisplay, 
- VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, -MOUSE_IMG_SIZE);
-INTON();
-  }
-}
+  int oldmode;
 
-void
-VGLMousePointerHide()
-{
-  if (VGLMouseVisible) {
-INTOFF();
-VGLMouseVisible = 0;
-__VGLBitmapCopy(, VGLMouseXpos, VGLMouseYpos, VGLDisplay, 
-VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, 
MOUSE_IMG_SIZE);
-INTON();
-  }
-}
-
-void
-VGLMouseMode(int mode)
-{
+  INTOFF();
+  oldmode = VGLMouseShown;
   if (mode == VGL_MOUSESHOW) {
 if (VGLMouseShown == VGL_MOUSEHIDE) {
-  VGLMousePointerShow();
   VGLMouseShown = VGL_MOUSESHOW;
+  __VGLBitmapCopy(, VGLMouseXpos, VGLMouseYpos, VGLDisplay, 
+  VGLMouseXpos, VGLMouseYpos,
+  MOUSE_IMG_SIZE, -MOUSE_IMG_SIZE);
 }
   }
   else {
 if (VGLMouseShown == VGL_MOUSESHOW) {
-  VGLMousePointerHide();
   VGLMouseShown = VGL_MOUSEHIDE;
+  __VGLBitmapCopy(, VGLMouseXpos, VGLMouseYpos, VGLDisplay, 
+  VGLMouseXpos, VGLMouseYpos,
+  MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
 }
   }
+  INTON();
+  return oldmode;
 }
 
 void
+VGLMouseMode(int mode)
+{
+  __VGLMouseMode(mode);
+}
+
+static void
 VGLMouseAction(int dummy)  
 {
   struct 

svn commit: r346761 - head/lib/libvgl

2019-04-26 Thread Bruce Evans
Author: bde
Date: Fri Apr 26 18:28:54 2019
New Revision: 346761
URL: https://svnweb.freebsd.org/changeset/base/346761

Log:
  Use __VGLBitmapCopy() directly to show the mouse cursor.  The mouse
  cursor must be merged with the shadow buffer on the way to the screen,
  and __VGLBitmapCopy() now has an option to do exactly that.  This is
  insignificantly less efficient.

Modified:
  head/lib/libvgl/mouse.c

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Fri Apr 26 18:25:59 2019(r346760)
+++ head/lib/libvgl/mouse.c Fri Apr 26 18:28:54 2019(r346761)
@@ -105,24 +105,11 @@ static volatile sig_atomic_t VGLMsuppressint;
 void
 VGLMousePointerShow()
 {
-  byte buf[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE*4];
-  VGLBitmap buffer =
-VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, buf);
-  int pos;
-
   if (!VGLMouseVisible) {
 INTOFF();
 VGLMouseVisible = 1;
-buffer.PixelBytes = VGLDisplay->PixelBytes;
-__VGLBitmapCopy(, VGLMouseXpos, VGLMouseYpos, 
-, 0, 0, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
-for (pos = 0; pos <  MOUSE_IMG_SIZE*MOUSE_IMG_SIZE; pos++)
-  if (VGLMouseAndMask->Bitmap[pos])
-bcopy(>Bitmap[pos*VGLDisplay->PixelBytes],
-  [pos*VGLDisplay->PixelBytes],
-  VGLDisplay->PixelBytes);
-__VGLBitmapCopy(, 0, 0, VGLDisplay, 
- VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
+__VGLBitmapCopy(, VGLMouseXpos, VGLMouseYpos, VGLDisplay, 
+ VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, -MOUSE_IMG_SIZE);
 INTON();
   }
 }
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346754 - head/lib/libvgl

2019-04-26 Thread Bruce Evans
Author: bde
Date: Fri Apr 26 16:38:23 2019
New Revision: 346754
URL: https://svnweb.freebsd.org/changeset/base/346754

Log:
  Merge __VGLGetXY() back into VGLGetXY().  They were split to simplify
  the organization of fixes for the mouse cursor, but after optimizations
  VGLGetXY() automatically avoids the mouse cursor.

Modified:
  head/lib/libvgl/simple.c

Modified: head/lib/libvgl/simple.c
==
--- head/lib/libvgl/simple.cFri Apr 26 16:26:01 2019(r346753)
+++ head/lib/libvgl/simple.cFri Apr 26 16:38:23 2019(r346754)
@@ -133,12 +133,19 @@ set_planar:
   }
 }
 
-static u_long
-__VGLGetXY(VGLBitmap *object, int x, int y)
+u_long
+VGLGetXY(VGLBitmap *object, int x, int y)
 {
-  int offset;
   u_long color;
+  int offset;
 
+  VGLCheckSwitch();
+  if (x<0 || x>=object->VXsize || y<0 || y>=object->VYsize)
+return 0;
+  if (object == VGLDisplay)
+object = 
+  else if (object->Type != MEMBUF)
+return 0;  /* invalid */
   offset = (y * object->VXsize + x) * object->PixelBytes;
   switch (object->PixelBytes) {
   case 1:
@@ -155,19 +162,6 @@ __VGLGetXY(VGLBitmap *object, int x, int y)
 return le32toh(color);
   }
   return 0;/* invalid */
-}
-
-u_long
-VGLGetXY(VGLBitmap *object, int x, int y)
-{
-  VGLCheckSwitch();
-  if (x<0 || x>=object->VXsize || y<0 || y>=object->VYsize)
-return 0;
-  if (object == VGLDisplay)
-object = 
-  else if (object->Type != MEMBUF)
-return 0;  /* invalid */
-  return __VGLGetXY(object, x, y);
 }
 
  /*
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346752 - head/lib/libvgl

2019-04-26 Thread Bruce Evans
Author: bde
Date: Fri Apr 26 16:14:23 2019
New Revision: 346752
URL: https://svnweb.freebsd.org/changeset/base/346752

Log:
  In VGLClear(), check for the overlap of the mouse cursor in the whole
  display, not just in the unpanned top left corner.  This currently
  makes no difference since the kernel erroneously doesn't allow moving
  the cursor completely outside of the unpanned corner.

Modified:
  head/lib/libvgl/simple.c

Modified: head/lib/libvgl/simple.c
==
--- head/lib/libvgl/simple.cFri Apr 26 15:43:14 2019(r346751)
+++ head/lib/libvgl/simple.cFri Apr 26 16:14:23 2019(r346752)
@@ -476,7 +476,7 @@ VGLClear(VGLBitmap *object, u_long color)
   VGLCheckSwitch();
   if (object == VGLDisplay) {
 VGLMouseFreeze();
-mouseoverlap = VGLMouseOverlap(0, 0, object->Xsize, object->Ysize);
+mouseoverlap = VGLMouseOverlap(0, 0, object->VXsize, object->VYsize);
 if (mouseoverlap)
   VGLMousePointerHide();
 VGLClear(, color);
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346747 - head/lib/libvgl

2019-04-26 Thread Bruce Evans
Author: bde
Date: Fri Apr 26 14:44:20 2019
New Revision: 346747
URL: https://svnweb.freebsd.org/changeset/base/346747

Log:
  Remove save/restore of the crtc and gdc registers when showing and
  hiding the mouse cursor.  The showing and hiding is often done
  asynchronously in a not very safe signal handler, but the state of
  these registers and much more is protected from the signal handler
  in a better way by deferring mouse signals while the state is in use.

Modified:
  head/lib/libvgl/mouse.c

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Fri Apr 26 14:15:58 2019(r346746)
+++ head/lib/libvgl/mouse.c Fri Apr 26 14:44:20 2019(r346747)
@@ -108,18 +108,11 @@ VGLMousePointerShow()
   byte buf[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE*4];
   VGLBitmap buffer =
 VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, buf);
-  byte crtcidx, crtcval, gdcidx, gdcval;
   int pos;
 
   if (!VGLMouseVisible) {
 INTOFF();
 VGLMouseVisible = 1;
-if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) {
-  crtcidx = inb(0x3c4);
-  crtcval = inb(0x3c5);
-  gdcidx = inb(0x3ce);
-  gdcval = inb(0x3cf);
-}
 buffer.PixelBytes = VGLDisplay->PixelBytes;
 __VGLBitmapCopy(, VGLMouseXpos, VGLMouseYpos, 
 , 0, 0, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
@@ -130,12 +123,6 @@ VGLMousePointerShow()
   VGLDisplay->PixelBytes);
 __VGLBitmapCopy(, 0, 0, VGLDisplay, 
  VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
-if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) {
-  outb(0x3c4, crtcidx);
-  outb(0x3c5, crtcval);
-  outb(0x3ce, gdcidx);
-  outb(0x3cf, gdcval);
-}
 INTON();
   }
 }
@@ -143,25 +130,11 @@ VGLMousePointerShow()
 void
 VGLMousePointerHide()
 {
-  byte crtcidx, crtcval, gdcidx, gdcval;
-
   if (VGLMouseVisible) {
 INTOFF();
 VGLMouseVisible = 0;
-if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) {
-  crtcidx = inb(0x3c4);
-  crtcval = inb(0x3c5);
-  gdcidx = inb(0x3ce);
-  gdcval = inb(0x3cf);
-}
 __VGLBitmapCopy(, VGLMouseXpos, VGLMouseYpos, VGLDisplay, 
 VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, 
MOUSE_IMG_SIZE);
-if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) {
-  outb(0x3c4, crtcidx);
-  outb(0x3c5, crtcval);
-  outb(0x3ce, gdcidx);
-  outb(0x3cf, gdcval);
-}
 INTON();
   }
 }
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346745 - head/lib/libvgl

2019-04-26 Thread Bruce Evans
Author: bde
Date: Fri Apr 26 13:49:06 2019
New Revision: 346745
URL: https://svnweb.freebsd.org/changeset/base/346745

Log:
  Fix the only known remaining (libvgl) bug for 24-bit modes, and enable
  support for 24-bit modes.
  
  The non-segmented case has worked for a long time, but the segmented
  case could never have worked since 24-bit accesses may cross a window
  boundary but the window was not changed in the middle of the specialized
  24-bit accesses for writing a single pixel.

Modified:
  head/lib/libvgl/main.c
  head/lib/libvgl/simple.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Fri Apr 26 13:22:54 2019(r346744)
+++ head/lib/libvgl/main.c  Fri Apr 26 13:49:06 2019(r346745)
@@ -42,8 +42,6 @@ __FBSDID("$FreeBSD$");
 #include 
 #include "vgl.h"
 
-/* XXX Direct Color 24bits modes unsupported */
-
 #define min(x, y)  (((x) < (y)) ? (x) : (y))
 #define max(x, y)  (((x) > (y)) ? (x) : (y))
 
@@ -223,11 +221,9 @@ VGLInit(int mode)
 case 2:
   VGLDisplay->Type = VIDBUF16;
   break;
-#if notyet
 case 3:
   VGLDisplay->Type = VIDBUF24;
   break;
-#endif
 case 4:
   VGLDisplay->Type = VIDBUF32;
   break;

Modified: head/lib/libvgl/simple.c
==
--- head/lib/libvgl/simple.cFri Apr 26 13:22:54 2019(r346744)
+++ head/lib/libvgl/simple.cFri Apr 26 13:49:06 2019(r346745)
@@ -51,7 +51,7 @@ static byte VGLSavePaletteBlue[256];
 void
 VGLSetXY(VGLBitmap *object, int x, int y, u_long color)
 {
-  int offset, undermouse;
+  int offset, soffset, undermouse;
 
   VGLCheckSwitch();
   if (x>=0 && xVXsize && y>=0 && yVYsize) {
@@ -67,7 +67,6 @@ VGLSetXY(VGLBitmap *object, int x, int y, u_long color
   switch (object->Type) {
   case VIDBUF8S:
   case VIDBUF16S:
-  case VIDBUF24S:
   case VIDBUF32S:
 offset = VGLSetSegment(offset);
 /* FALLTHROUGH */
@@ -89,6 +88,25 @@ VGLSetXY(VGLBitmap *object, int x, int y, u_long color
   break;
 case 4:
   memcpy(>Bitmap[offset], , 4);
+  break;
+}
+break;
+  case VIDBUF24S:
+soffset = VGLSetSegment(offset);
+color = htole32(color);
+switch (VGLAdpInfo.va_window_size - soffset) {
+case 1:
+  memcpy(>Bitmap[soffset], , 1);
+  soffset = VGLSetSegment(offset + 1);
+  memcpy(>Bitmap[soffset], (byte *) + 1, 2);
+  break;
+case 2:
+  memcpy(>Bitmap[soffset], , 2);
+  soffset = VGLSetSegment(offset + 2);
+  memcpy(>Bitmap[soffset], (byte *) + 2, 1);
+  break;
+default:
+  memcpy(>Bitmap[soffset], , 3);
   break;
 }
 break;
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346744 - head/lib/libvgl

2019-04-26 Thread Bruce Evans
Author: bde
Date: Fri Apr 26 13:22:54 2019
New Revision: 346744
URL: https://svnweb.freebsd.org/changeset/base/346744

Log:
  Restore the line width in VGLEnd().  The line width may be changed by
  VGLSetVScreenSize(), but is not restored by mode switches to at least
  standard text mode, so must be restored explicitly.  Standard text mode
  displayed blanks when the line width was doubled.

Modified:
  head/lib/libvgl/main.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Fri Apr 26 13:04:10 2019(r346743)
+++ head/lib/libvgl/main.c  Fri Apr 26 13:22:54 2019(r346744)
@@ -64,6 +64,7 @@ static unsigned int VGLCurWindow;
 static int VGLInitDone = 0;
 static video_info_t VGLOldModeInfo;
 static vid_info_t VGLOldVInfo;
+static int VGLOldVXsize;
 
 void
 VGLEnd()
@@ -85,6 +86,8 @@ struct vt_mode smode;
 munmap(VGLMem, VGLAdpInfo.va_window_size);
   }
 
+  ioctl(0, FBIO_SETLINEWIDTH, );
+
   if (VGLOldMode >= M_VESA_BASE)
 ioctl(0, _IO('V', VGLOldMode - M_VESA_BASE), 0);
   else
@@ -322,6 +325,7 @@ VGLInit(int mode)
   depth = VGLModeInfo.vi_depth;
   if (depth == 15)
 depth = 16;
+  VGLOldVXsize =
   VGLDisplay->VXsize = VGLAdpInfo.va_line_width
   *8/(depth/VGLModeInfo.vi_planes);
   VGLDisplay->VYsize = 
VGLBufSize/VGLModeInfo.vi_planes/VGLAdpInfo.va_line_width;
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346743 - head/lib/libvgl

2019-04-26 Thread Bruce Evans
Author: bde
Date: Fri Apr 26 13:04:10 2019
New Revision: 346743
URL: https://svnweb.freebsd.org/changeset/base/346743

Log:
  Fix an off-by-1 error for copying overlapping bitmaps in r346416.  For
  nonzero height, the first line in the original order was not copied, and
  for zero height, garbage lines before the first were copied until a crash
  occurred.

Modified:
  head/lib/libvgl/bitmap.c

Modified: head/lib/libvgl/bitmap.c
==
--- head/lib/libvgl/bitmap.cFri Apr 26 13:00:25 2019(r346742)
+++ head/lib/libvgl/bitmap.cFri Apr 26 13:04:10 2019(r346743)
@@ -207,7 +207,7 @@ __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
   yextra = 0;
   ystep = 1;
   if (src->Bitmap == dst->Bitmap && srcy < dsty) {
-yend = srcy;
+yend = srcy - 1;
 yextra = hight - 1;
 ystep = -1;
   }
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r346593 - head/sys/sys

2019-04-26 Thread Bruce Evans

On Fri, 26 Apr 2019, Mark Johnston wrote:


On Fri, Apr 26, 2019 at 10:38:36AM +0300, Konstantin Belousov wrote:

On Fri, Apr 26, 2019 at 02:04:56AM -0400, Mark Johnston wrote:

On Thu, Apr 25, 2019 at 11:22:22AM +0300, Konstantin Belousov wrote:

On Thu, Apr 25, 2019 at 07:38:21AM +0200, Wojciech Macek wrote:

Intel does not reorder reads against the condition "if" here. I know for
sure that ARM does, but therestill might be some other architectures that
also suffers such behavior - I just don't have any means to verify.
I remember the discussion for rS302292 where we agreed that this kind of
patches should be the least impacting in perfomrance as possible. Adding
unconditional memory barrier causes significant performance drop on Intel,
where in fact, the issue was never seen.


Atomic_thread_fence_acq() is nop on x86, or rather, it is compiler memory
barrier.  If you need read/read fence on some architectures, I am sure
that you need compiler barrier on all.


To add a bit, one reason to prefer atomic(9) to explicit fences is
precisely because it issues fences only when required by a given
CPU architecture.  There is no "unconditional memory barrier" added by
the diff even without the #ifdef.

Well, atomic_thread_fence_acq() is the explicit fence.  And on x86 it
does add unconditional compiler memory barrier.


I only mean that with atomic_thread_fence_acq() on x86, the CPU does not
see any fences.

Based on the original commit it seems that a compiler barrier is
required on all platforms, at a minimum.


buf_ring.h has some volatile variables which might give sufficient barriers.
But no one knows what volatile does, so reasoning about it is even harder
than reasoning about ordering from atomic ops.  I think the volatiles give
program order for the volatile variables only (plus ordering of other variables
from dependencies on the volatile variables), while the compiler barrier
gives program order for all variables.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346678 - head/lib/libvgl

2019-04-25 Thread Bruce Evans
Author: bde
Date: Thu Apr 25 15:48:23 2019
New Revision: 346678
URL: https://svnweb.freebsd.org/changeset/base/346678

Log:
  Restore doing nothing for calls to VGLEnd() after the first. I broke this
  in r346631.  VGLEnd() clears some state variables as it restores state,
  but not all of them, so it still needs to clear a single state variable
  to indicate that it has completed.  Put this clearing back where it was
  (at the start instead of the end) to avoid moving bugs in the signal
  handling.

Modified:
  head/lib/libvgl/main.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Thu Apr 25 15:37:28 2019(r346677)
+++ head/lib/libvgl/main.c  Thu Apr 25 15:48:23 2019(r346678)
@@ -73,6 +73,7 @@ struct vt_mode smode;
 
   if (!VGLInitDone)
 return;
+  VGLInitDone = 0;
   signal(SIGUSR1, SIG_IGN);
   signal(SIGUSR2, SIG_IGN);
   VGLSwitchPending = 0;
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346641 - head/lib/libvgl

2019-04-24 Thread Bruce Evans
Author: bde
Date: Wed Apr 24 16:03:35 2019
New Revision: 346641
URL: https://svnweb.freebsd.org/changeset/base/346641

Log:
  Avoid hiding and unhiding the mouse cursor when copying bitmaps to the
  screen.  Instead, copy a merged bitmap 1 line at a time.
  
  This fixes flashing of the cursor and is faster in all modes (especially
  in planar modes).

Modified:
  head/lib/libvgl/bitmap.c
  head/lib/libvgl/mouse.c
  head/lib/libvgl/vgl.h

Modified: head/lib/libvgl/bitmap.c
==
--- head/lib/libvgl/bitmap.cWed Apr 24 15:54:18 2019(r346640)
+++ head/lib/libvgl/bitmap.cWed Apr 24 16:03:35 2019(r346641)
@@ -167,8 +167,17 @@ int
 __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
  VGLBitmap *dst, int dstx, int dsty, int width, int hight)
 {
-  int srcline, dstline, yend, yextra, ystep;
-
+  byte *buffer, *p;
+  int mousemerge, srcline, dstline, yend, yextra, ystep;
+  
+  mousemerge = 0;
+  if (hight < 0) {
+hight = -hight;
+mousemerge = (dst == VGLDisplay &&
+ VGLMouseOverlap(dstx, dsty, width, hight));
+if (mousemerge)
+  buffer = alloca(width*src->PixelBytes);
+  }
   if (srcx>src->VXsize || srcy>src->VYsize
|| dstx>dst->VXsize || dsty>dst->VYsize)
 return -1;  
@@ -204,8 +213,13 @@ __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
   }
   for (srcline = srcy + yextra, dstline = dsty + yextra; srcline != yend;
srcline += ystep, dstline += ystep) {
-WriteVerticalLine(dst, dstx, dstline, width, 
-  src->Bitmap+(srcline*src->VXsize+srcx)*dst->PixelBytes);
+p = src->Bitmap+(srcline*src->VXsize+srcx)*dst->PixelBytes;
+if (mousemerge && VGLMouseOverlap(dstx, dstline, width, 1)) {
+  bcopy(p, buffer, width*src->PixelBytes);
+  p = buffer;
+  VGLMouseMerge(dstx, dstline, width, p);
+}
+WriteVerticalLine(dst, dstx, dstline, width, p);
   }
   return 0;
 }
@@ -214,36 +228,29 @@ int
 VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
  VGLBitmap *dst, int dstx, int dsty, int width, int hight)
 {
-  int error, mouseoverlap;
+  int error;
 
+  if (hight < 0)
+return -1;
   if (src == VGLDisplay)
 src = 
   if (src->Type != MEMBUF)
 return -1; /* invalid */
   if (dst == VGLDisplay) {
 VGLMouseFreeze();
-mouseoverlap = VGLMouseOverlap(dstx, dsty, width, hight);
-if (mouseoverlap)
-  VGLMousePointerHide();
+__VGLBitmapCopy(src, srcx, srcy, , dstx, dsty, width, hight);
 error = __VGLBitmapCopy(src, srcx, srcy, , dstx, dsty,
 width, hight);
-if (error != 0) {
-  if (mouseoverlap)
-VGLMousePointerShow();
-  VGLMouseUnFreeze();
+if (error != 0)
   return error;
-}
 src = 
 srcx = dstx;
 srcy = dsty;
   } else if (dst->Type != MEMBUF)
 return -1; /* invalid */
-  error = __VGLBitmapCopy(src, srcx, srcy, dst, dstx, dsty, width, hight);
-  if (dst == VGLDisplay) {
-if (mouseoverlap)
-  VGLMousePointerShow();
+  error = __VGLBitmapCopy(src, srcx, srcy, dst, dstx, dsty, width, -hight);
+  if (dst == VGLDisplay)
 VGLMouseUnFreeze();
-  }
   return error;
 }
 

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Wed Apr 24 15:54:18 2019(r346640)
+++ head/lib/libvgl/mouse.c Wed Apr 24 16:03:35 2019(r346641)
@@ -356,6 +356,25 @@ VGLMouseOverlap(int x, int y, int width, int hight)
 }
 
 void
+VGLMouseMerge(int x, int y, int width, byte *line)
+{
+  int pos, x1, xend, xstart;
+
+  xstart = x;
+  if (xstart < VGLMouseXpos)
+xstart = VGLMouseXpos;
+  xend = x + width;
+  if (xend > VGLMouseXpos + MOUSE_IMG_SIZE)
+xend = VGLMouseXpos + MOUSE_IMG_SIZE;
+  for (x1 = xstart; x1 < xend; x1++) {
+pos = (y - VGLMouseYpos) * MOUSE_IMG_SIZE + x1 - VGLMouseXpos;
+if (VGLMouseAndMask->Bitmap[pos])
+  bcopy(>Bitmap[pos * VGLDisplay->PixelBytes],
+[(x1 - x) * VGLDisplay->PixelBytes], VGLDisplay->PixelBytes);
+  }
+}
+
+void
 VGLMouseUnFreeze()
 {
   INTON();

Modified: head/lib/libvgl/vgl.h
==
--- head/lib/libvgl/vgl.h   Wed Apr 24 15:54:18 2019(r346640)
+++ head/lib/libvgl/vgl.h   Wed Apr 24 16:03:35 2019(r346641)
@@ -136,6 +136,7 @@ void VGLMouseRestore(void);
 int VGLMouseStatus(int *x, int *y, char *buttons);
 void VGLMouseFreeze(void);
 int VGLMouseFreezeXY(int x, int y);
+void VGLMouseMerge(int x, int y, int width, byte *line);
 int VGLMouseOverlap(int x, int y, int width, int hight);
 void VGLMouseUnFreeze(void);
 /* simple.c */
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346639 - head/lib/libvgl

2019-04-24 Thread Bruce Evans
Author: bde
Date: Wed Apr 24 15:35:29 2019
New Revision: 346639
URL: https://svnweb.freebsd.org/changeset/base/346639

Log:
  Refactor mouse freezing and fix some minor bugs.
  
  VGLMouseFreeze() now only defers mouse signals and leaves it to higher
  levels to hide and unhide the mouse cursor if necessary.  (It is never
  necessary, but is done to simplify the implementation.  It is slow and
  flashes the cursor.  It is still done for copying bitmaps and clearing.)
  
  VGLMouseUnFreeze() now only undoes 1 level of freezing.  Its old
  optimization to reduce mouse redrawing is too hard to do with unhiding
  in higher levels, and its undoing of multiple levels was a historical
  mistake.
  
  VGLMouseOverlap() determines if a region overlaps the (full) mouse region.
  
  VGLMouseFreezeXY() is the freezing and a precise overlap check combined
  for the special case of writing a single pixel.  This is the single-pixel
  case of the old VGLMouseFreeze() with cleanups.
  
  Fixes:
  - check in more cases that the application didn't pass an invalid VIDBUF
  - check for errors from copying a bitmap to the shadow buffer
  - freeze the mouse before writing to the shadow buffer in all cases.  This
was not done for the case of writing a single pixel (there was a race)
  - don't spell the #defined values for VGLMouseShown as 0, 1 or boolean.

Modified:
  head/lib/libvgl/bitmap.c
  head/lib/libvgl/mouse.c
  head/lib/libvgl/simple.c
  head/lib/libvgl/vgl.h

Modified: head/lib/libvgl/bitmap.c
==
--- head/lib/libvgl/bitmap.cWed Apr 24 15:02:59 2019(r346638)
+++ head/lib/libvgl/bitmap.cWed Apr 24 15:35:29 2019(r346639)
@@ -214,23 +214,36 @@ int
 VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
  VGLBitmap *dst, int dstx, int dsty, int width, int hight)
 {
-  int error;
+  int error, mouseoverlap;
 
   if (src == VGLDisplay)
 src = 
   if (src->Type != MEMBUF)
 return -1; /* invalid */
   if (dst == VGLDisplay) {
-VGLMouseFreeze(dstx, dsty, width, hight, 0);
-__VGLBitmapCopy(src, srcx, srcy, , dstx, dsty, width, hight);
+VGLMouseFreeze();
+mouseoverlap = VGLMouseOverlap(dstx, dsty, width, hight);
+if (mouseoverlap)
+  VGLMousePointerHide();
+error = __VGLBitmapCopy(src, srcx, srcy, , dstx, dsty,
+width, hight);
+if (error != 0) {
+  if (mouseoverlap)
+VGLMousePointerShow();
+  VGLMouseUnFreeze();
+  return error;
+}
 src = 
 srcx = dstx;
 srcy = dsty;
   } else if (dst->Type != MEMBUF)
 return -1; /* invalid */
   error = __VGLBitmapCopy(src, srcx, srcy, dst, dstx, dsty, width, hight);
-  if (dst == VGLDisplay)
+  if (dst == VGLDisplay) {
+if (mouseoverlap)
+  VGLMousePointerShow();
 VGLMouseUnFreeze();
+  }
   return error;
 }
 

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Wed Apr 24 15:02:59 2019(r346638)
+++ head/lib/libvgl/mouse.c Wed Apr 24 15:35:29 2019(r346639)
@@ -89,7 +89,7 @@ static VGLBitmap VGLMouseStdOrMask = 
 VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdOrMask);
 static VGLBitmap *VGLMouseAndMask, *VGLMouseOrMask;
 static int VGLMouseVisible = 0;
-static int VGLMouseShown = 0;
+static int VGLMouseShown = VGL_MOUSEHIDE;
 static int VGLMouseXpos = 0;
 static int VGLMouseYpos = 0;
 static int VGLMouseButtons = 0;
@@ -316,48 +316,47 @@ VGLMouseStatus(int *x, int *y, char *buttons)
   return VGLMouseShown;
 }
 
-int
-VGLMouseFreeze(int x, int y, int width, int hight, u_long color)
+void
+VGLMouseFreeze(void)
 {
-INTOFF();
-if (width > 1 || hight > 1 || (color & 0xc000) == 0) { /* bitmap */
-  if (VGLMouseShown == 1) {
-int overlap;
+  INTOFF();
+}
 
-if (x > VGLMouseXpos)
-  overlap = (VGLMouseXpos + MOUSE_IMG_SIZE) - x;
-else
-  overlap = (x + width) - VGLMouseXpos;
-if (overlap > 0) {
-  if (y > VGLMouseYpos)
-overlap = (VGLMouseYpos + MOUSE_IMG_SIZE) - y;
-  else
-overlap = (y + hight) - VGLMouseYpos;
-  if (overlap > 0)
-VGLMousePointerHide();
-} 
-  }
-}
-else { /* bit */
-  if (VGLMouseShown &&
-  x >= VGLMouseXpos && x < VGLMouseXpos + MOUSE_IMG_SIZE &&
-  y >= VGLMouseYpos && y < VGLMouseYpos + MOUSE_IMG_SIZE) {
-if (color & 0x8000) {  /* Set */
-  if (VGLMouseAndMask->Bitmap 
-[(y-VGLMouseYpos)*MOUSE_IMG_SIZE+(x-VGLMouseXpos)]) {
-return 1;
-  }   
-}   
-  }   
-}
+int
+VGLMouseFreezeXY(int x, int y)
+{
+  INTOFF();
+  if (VGLMouseShown != VGL_MOUSESHOW)
+return 0;
+  if (x >= VGLMouseXpos && x < VGLMouseXpos + MOUSE_IMG_SIZE &&
+  y >= 

svn commit: r346631 - head/lib/libvgl

2019-04-24 Thread Bruce Evans
Author: bde
Date: Wed Apr 24 13:15:56 2019
New Revision: 346631
URL: https://svnweb.freebsd.org/changeset/base/346631

Log:
  Fix some races and screeen clearing in VGLEnd().
  
  The mouse signal SIGUSR2 was not turned off for normal termination and
  in some other cases.  Thus mouse signals arriving after the frame
  buffer was unmapped always caused fatal traps.  The fatal traps occurred
  about 1 time in 5 if the mouse was wiggled while vgl is ending.
  
  The screen switch signal SIGUSR1 was turned off after clearing the
  flag that it sets.  Unlike the mouse signal, this signal is handled
  synchronously, but VGLEnd() does screen clearing which does the
  synchronous handling.  This race is harder to lose.  I think it can
  get vgl into deadlocked state (waiting in the screen switch handler
  with SIGUSR1 to leave that state already turned off).
  
  Turn off the mouse cursor before clearing the screen in VGLEnd().
  Otherwise, clearing is careful to not clear the mouse cursor.  Undrawing
  an active mouse cursor uses a lot of state, so is dangerous for abnormal
  termination, but so is clearing.  Clearing is slow and is usually not
  needed, since the kernel also does it (not quite right).

Modified:
  head/lib/libvgl/main.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Wed Apr 24 09:05:45 2019(r346630)
+++ head/lib/libvgl/main.c  Wed Apr 24 13:15:56 2019(r346631)
@@ -73,11 +73,11 @@ struct vt_mode smode;
 
   if (!VGLInitDone)
 return;
-  VGLInitDone = 0;
+  signal(SIGUSR1, SIG_IGN);
+  signal(SIGUSR2, SIG_IGN);
   VGLSwitchPending = 0;
   VGLAbortPending = 0;
-
-  signal(SIGUSR1, SIG_IGN);
+  VGLMousePointerHide();
 
   if (VGLMem != MAP_FAILED) {
 VGLClear(VGLDisplay, 0);
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346580 - head/lib/libvgl

2019-04-22 Thread Bruce Evans
Author: bde
Date: Mon Apr 22 19:31:16 2019
New Revision: 346580
URL: https://svnweb.freebsd.org/changeset/base/346580

Log:
  Fix mouse cursor coloring in depths > 8 (previously, a hack that only
  worked right for white interiors and black borders was used).  Advertise
  this by changing the default colors to a red interior and a white
  border (the same as the kernel default).  Add undocumented env variables
  for changing these colors.  Also change to the larger and better-shaped
  16x10 cursor sometimes used in the kernel.  The kernel choice is
  fancier, but libvgl is closer to supporting the larger cursors needed
  in newer modes.
  
  The (n)and-or logic for the cursor doesn't work right for more than 2
  colors.  The (n)and part only masks out all color bits for the pixel
  under the cursor when all bits are set in the And mask.  With more
  complicated logic, the non-masked bits could be used to implement
  translucent cursors, but they actually just gave strange colors
  (especially in packed and planar modes where the bits are indirect
  through 1 or 2 palettes so it is hard to predict the final color).
  They also gave a bug for writing pixels under the cursor.  The
  non-masked bits under the cursor were not combined in this case.
  
  Drop support for combining with bits under the cursor by making any nonzero
  value in the And mask mean all bits set.
  
  Convert the Or mask (which is represented as a half-initialized 256-color
  bitmap) to a fully initialized bitmap with the correct number of colors.
  The 256-color representation must be as in 3:3:2 direct mode iff the final
  bitmap has more than 256 colors.  The conversion of colors is not very
  efficient, so convert at initialization time.

Modified:
  head/lib/libvgl/bitmap.c
  head/lib/libvgl/mouse.c
  head/lib/libvgl/simple.c
  head/lib/libvgl/vgl.h

Modified: head/lib/libvgl/bitmap.c
==
--- head/lib/libvgl/bitmap.cMon Apr 22 19:24:21 2019(r346579)
+++ head/lib/libvgl/bitmap.cMon Apr 22 19:31:16 2019(r346580)
@@ -274,3 +274,27 @@ VGLBitmapAllocateBits(VGLBitmap *object)
 return -1;
   return 0;
 }
+
+void
+VGLBitmapCvt(VGLBitmap *src, VGLBitmap *dst)
+{
+  u_long color;
+  int dstpos, i, pb, size, srcpb, srcpos;
+
+  size = src->VXsize * src->VYsize;
+  srcpb = src->PixelBytes;
+  if (srcpb <= 0)
+srcpb = 1;
+  pb = dst->PixelBytes;
+  if (pb == srcpb) {
+bcopy(src->Bitmap, dst->Bitmap, size * pb);
+return;
+  }
+  if (srcpb != 1)
+return;/* not supported */
+  for (srcpos = dstpos = 0; srcpos < size; srcpos++) {
+color = VGLrgb332ToNative(src->Bitmap[srcpos]);
+for (i = 0; i < pb; i++, color >>= 8)
+dst->Bitmap[dstpos++] = color;
+  }
+}

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Mon Apr 22 19:24:21 2019(r346579)
+++ head/lib/libvgl/mouse.c Mon Apr 22 19:31:16 2019(r346580)
@@ -39,7 +39,11 @@ __FBSDID("$FreeBSD$");
 #include 
 #include "vgl.h"
 
-#define X 0xff
+#define BORDER 0xff/* default border -- light white in rgb 3:3:2 */
+#define INTERIOR 0xa0  /* default interior -- red in rgb 3:3:2 */
+#define X  0xff/* any nonzero in And mask means part of cursor */
+#define B  BORDER
+#define I  INTERIOR
 static byte StdAndMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -49,34 +53,36 @@ static byte StdAndMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] 
X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,
X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
+   X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,
+   X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,
X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
-   0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,0,
-   0,0,0,X,X,X,X,X,0,0,0,0,0,0,0,0,
-   0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,
-   0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+   X,X,X,0,X,X,X,X,0,0,0,0,0,0,0,0,
+   X,X,0,0,X,X,X,X,0,0,0,0,0,0,0,0,
+   0,0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,
+   0,0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,
+   0,0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,
 };
 static byte StdOrMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
-   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   0,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   0,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   0,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
-   0,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
-   0,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,
-   0,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
-   0,X,X,0,X,0,0,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   

Re: svn commit: r346554 - head/sys/netinet

2019-04-22 Thread Bruce Evans

On Mon, 22 Apr 2019, Bjoern A. Zeeb wrote:


On 22 Apr 2019, at 14:20, Bjoern A. Zeeb wrote:

Log:
  Remove some excessive brackets.

  No functional change.


But it includes a stye bug; sorry; I had re-indented the lines to validate 
the change.  Ill remedy this with the follow-up commit which will split 
that block up anyway.


Also, it removes excessive parentheses, not excessive brackets.

I think excessive brackets are just syntax errors.  E.g., a[[i]].

Excessive braces are not syntax errors, but I've never more than single
excessive ones.  E.g.,

if (foo != 0) {
bar();
}

is a common style bug, but

if (foo != 0) {{
bar();
  }}

s unusual.

Bruce
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346488 - head/lib/libvgl

2019-04-21 Thread Bruce Evans
Author: bde
Date: Sun Apr 21 16:17:35 2019
New Revision: 346488
URL: https://svnweb.freebsd.org/changeset/base/346488

Log:
  Use a shadow buffer and never read from the frame buffer.  Remove large slow
  code for reading from the frame buffer.
  
  Reading from the frame buffer is usually much slower than writing to
  the frame buffer.  Typically 10 to 100 times slower.  It old modes,
  it takes many more PIOs, and in newer modes with no PIOs writes are
  often write-combined while reads remain uncached.
  
  Reading from the frame buffer is not very common, so this change doesn't
  give speedups of 10 to 100 times.  My main test case is a floodfill()
  function that reads about as many pixels as it writes.  The speedups
  are typically a factor of 2 to 4.
  
  Duplicating writes to the shadow buffer is slower when no reads from the
  frame buffer are done, but reads are often done for the pixels under the
  mouse cursor, and doing these reads from the shadow buffer more than
  compensates for the overhead of writing the shadow buffer in at least the
  slower modes.  Management of the mouse cursor also becomes simpler.
  
  The shadow buffer doesn't take any extra memory, except twice as much
  in old 4-plane modes.  A buffer for holding a copy of the frame buffer
  was allocated up front for use in the screen switching signal handler.
  This wasn't changed when the handler was made async-signal safe.  Use
  the same buffer the shadow (but make it twice as large in the 4-plane
  modes), and remove large special code for writing it as well as large
  special code for reading ut.  It used to have a rawer format in the
  4-plane modes.  Now it has a bitmap format which takes twice as much
  memory but can be written almost as fast without special code.
  
  VIDBUFs that are not the whole frame buffer were never supported, and the
  change depends on this.  Check for invalid VIDBUFs in some places and do
  nothing.  The removed code did something not so good.

Modified:
  head/lib/libvgl/bitmap.c
  head/lib/libvgl/main.c
  head/lib/libvgl/mouse.c
  head/lib/libvgl/simple.c
  head/lib/libvgl/vgl.h

Modified: head/lib/libvgl/bitmap.c
==
--- head/lib/libvgl/bitmap.cSun Apr 21 14:45:18 2019(r346487)
+++ head/lib/libvgl/bitmap.cSun Apr 21 16:17:35 2019(r346488)
@@ -163,108 +163,6 @@ WriteVerticalLine(VGLBitmap *dst, int x, int y, int wi
   }
 }
 
-static void
-ReadVerticalLine(VGLBitmap *src, int x, int y, int width, byte *line)
-{
-  int i, bit, pos, count, planepos, start_offset, end_offset, offset;
-  int width2, len;
-  byte *address;
-  byte *VGLPlane[4];
-
-  switch (src->Type) {
-  case VIDBUF4S:
-start_offset = (x & 0x07);
-end_offset = (x + width) & 0x07;
-count = (width + start_offset) / 8;
-if (end_offset)
-  count++;
-VGLPlane[0] = VGLBuf;
-VGLPlane[1] = VGLPlane[0] + count;
-VGLPlane[2] = VGLPlane[1] + count;
-VGLPlane[3] = VGLPlane[2] + count;
-for (i=0; i<4; i++) {
-  outb(0x3ce, 0x04);
-  outb(0x3cf, i);
-  pos = VGLAdpInfo.va_line_width*y + x/8;
-  for (width2 = count; width2 > 0; ) {
-   offset = VGLSetSegment(pos);
-   len = min(VGLAdpInfo.va_window_size - offset, width2);
-   bcopy(src->Bitmap + offset, [i][count - width2], len);
-   pos += len;
-   width2 -= len;
-  }
-}
-goto read_planar;
-  case VIDBUF4:
-address = src->Bitmap + VGLAdpInfo.va_line_width * y + x/8;
-start_offset = (x & 0x07);
-end_offset = (x + width) & 0x07;
-count = (width + start_offset) / 8;
-if (end_offset)
-  count++;
-VGLPlane[0] = VGLBuf;
-VGLPlane[1] = VGLPlane[0] + count;
-VGLPlane[2] = VGLPlane[1] + count;
-VGLPlane[3] = VGLPlane[2] + count;
-for (i=0; i<4; i++) {
-  outb(0x3ce, 0x04);
-  outb(0x3cf, i);
-  bcopy(address, [i][0], count);
-}
-read_planar:
-pos = 0;
-planepos = 0;
-bit = 7 - start_offset;
-while (pos < width) {
-  for (; bit >= 0 && pos < width; bit--, pos++) {
-line[pos] = (VGLPlane[0][planepos] & (1VXsize * y + x) * src->PixelBytes;
-while (width > 0) {
-  offset = VGLSetSegment(pos);
-  i = min(VGLAdpInfo.va_window_size - offset, width);
-  bcopy(src->Bitmap + offset, line, i);
-  line += i;
-  pos += i;
-  width -= i;
-}
-break;
-  case MEMBUF:
-  case VIDBUF8:
-  case VIDBUF16:
-  case VIDBUF24:
-  case VIDBUF32:
-address = src->Bitmap + (src->VXsize * y + x) * src->PixelBytes;
-bcopy(address, line, width * src->PixelBytes);
-break;
-  default:
-;
-  }
-}
-
 int
 __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
  VGLBitmap *dst, int dstx, int dsty, int width, int 

svn commit: r346486 - head/lib/libvgl

2019-04-21 Thread Bruce Evans
Author: bde
Date: Sun Apr 21 10:33:09 2019
New Revision: 346486
URL: https://svnweb.freebsd.org/changeset/base/346486

Log:
  Fix missing restoring of the mouse cursor position, the border color and the
  blank state after a screen switch.

Modified:
  head/lib/libvgl/main.c
  head/lib/libvgl/mouse.c
  head/lib/libvgl/simple.c
  head/lib/libvgl/vgl.h

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Sun Apr 21 09:13:56 2019(r346485)
+++ head/lib/libvgl/main.c  Sun Apr 21 10:33:09 2019(r346486)
@@ -436,6 +436,9 @@ VGLCheckSwitch()
   VGLDisplay->Xsize = VGLModeInfo.vi_width;
   VGLDisplay->Ysize = VGLModeInfo.vi_height;
   VGLSetVScreenSize(VGLDisplay, VGLDisplay->VXsize, VGLDisplay->VYsize);
+  VGLRestoreBlank();
+  VGLRestoreBorder();
+  VGLMouseRestore();
   VGLPanScreen(VGLDisplay, VGLDisplay->Xorigin, VGLDisplay->Yorigin);
   switch (VGLDisplay->Type) {
   case VIDBUF4S:

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Sun Apr 21 09:13:56 2019(r346485)
+++ head/lib/libvgl/mouse.c Sun Apr 21 10:33:09 2019(r346486)
@@ -272,6 +272,22 @@ VGLMouseInit(int mode)
   return 0;
 }
 
+void
+VGLMouseRestore(void)
+{
+  struct mouse_info mouseinfo;
+
+  INTOFF();
+  mouseinfo.operation = MOUSE_GETINFO;
+  if (ioctl(0, CONS_MOUSECTL, ) == 0) {
+mouseinfo.operation = MOUSE_MOVEABS;
+mouseinfo.u.data.x = VGLMouseXpos;
+mouseinfo.u.data.y = VGLMouseYpos;
+ioctl(0, CONS_MOUSECTL, );
+  }
+  INTON();
+}
+
 int
 VGLMouseStatus(int *x, int *y, char *buttons)
 {

Modified: head/lib/libvgl/simple.c
==
--- head/lib/libvgl/simple.cSun Apr 21 09:13:56 2019(r346485)
+++ head/lib/libvgl/simple.cSun Apr 21 10:33:09 2019(r346486)
@@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$");
 #include 
 #include "vgl.h"
 
+static int VGLBlank;
+static byte VGLBorderColor;
 static byte VGLSavePaletteRed[256];
 static byte VGLSavePaletteGreen[256];
 static byte VGLSavePaletteBlue[256];
@@ -637,6 +639,12 @@ VGLSetPaletteIndex(byte color, byte red, byte green, b
 }
 
 void
+VGLRestoreBorder(void)
+{
+  VGLSetBorder(VGLBorderColor);
+}
+
+void
 VGLSetBorder(byte color)
 {
   if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT && ioctl(0, KDENABIO, 0))
@@ -646,11 +654,18 @@ VGLSetBorder(byte color)
   outb(0x3C0,0x11); outb(0x3C0, color); 
   inb(0x3DA);
   outb(0x3C0, 0x20);
+  VGLBorderColor = color;
   if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
 ioctl(0, KDDISABIO, 0);
 }
 
 void
+VGLRestoreBlank(void)
+{
+  VGLBlankDisplay(VGLBlank);
+}
+
+void
 VGLBlankDisplay(int blank)
 {
   byte val;
@@ -660,6 +675,7 @@ VGLBlankDisplay(int blank)
   VGLCheckSwitch();
   outb(0x3C4, 0x01); val = inb(0x3C5); outb(0x3C4, 0x01);
   outb(0x3C5, ((blank) ? (val |= 0x20) : (val &= 0xDF)));
+  VGLBlank = blank;
   if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
 ioctl(0, KDDISABIO, 0);
 }

Modified: head/lib/libvgl/vgl.h
==
--- head/lib/libvgl/vgl.h   Sun Apr 21 09:13:56 2019(r346485)
+++ head/lib/libvgl/vgl.h   Sun Apr 21 10:33:09 2019(r346486)
@@ -130,6 +130,7 @@ void VGLMouseAction(int dummy);
 void VGLMouseSetImage(VGLBitmap *AndMask, VGLBitmap *OrMask);
 void VGLMouseSetStdImage(void);
 int VGLMouseInit(int mode);
+void VGLMouseRestore(void);
 int VGLMouseStatus(int *x, int *y, char *buttons);
 int VGLMouseFreeze(int x, int y, int width, int hight, u_long color);
 void VGLMouseUnFreeze(void);
@@ -142,6 +143,8 @@ void VGLFilledBox(VGLBitmap *object, int x1, int y1, i
 void VGLEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color);
 void VGLFilledEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long 
color);
 void VGLClear(VGLBitmap *object, u_long color);
+void VGLRestoreBlank(void);
+void VGLRestoreBorder(void);
 void VGLRestorePalette(void);
 void VGLSavePalette(void);
 void VGLSetPalette(byte *red, byte *green, byte *blue);
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346454 - head/lib/libvgl

2019-04-20 Thread Bruce Evans
Author: bde
Date: Sat Apr 20 20:29:03 2019
New Revision: 346454
URL: https://svnweb.freebsd.org/changeset/base/346454

Log:
  Make libvgl mostly work without superuser privilege in direct modes by
  not doing any unnecessary PIO instructions or refusing to start when the
  i/o privilege needed for these instructions cannot be acquired.
  
  This turns off useless palette management in direct modes.  Palette
  management had no useful effect since the hardware palette is not used
  in these modes.
  
  This transiently acquires i/o privilege if possible as needed to give
  VGLSetBorder() and VGLBlankDisplay() a chance of working.  Neither has
  much chance of working.  I was going to drop support for them in direct
  modes, but found that VGLBlankDisplay() still works with an old graphics
  card on a not so old LCD monitor.
  
  This has some good side effects: reduce glitches for managing the palette
  for screen switches, and speed up and reduce async-signal-unsafeness in
  mouse cursor drawing.

Modified:
  head/lib/libvgl/main.c
  head/lib/libvgl/mouse.c
  head/lib/libvgl/simple.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Sat Apr 20 17:16:36 2019(r346453)
+++ head/lib/libvgl/main.c  Sat Apr 20 20:29:03 2019(r346454)
@@ -93,7 +93,8 @@ struct vt_mode smode;
 size[2] = VGLOldVInfo.font_size;;
 ioctl(0, KDRASTER, size);
   }
-  ioctl(0, KDDISABIO, 0);
+  if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT)
+ioctl(0, KDDISABIO, 0);
   ioctl(0, KDSETMODE, KD_TEXT);
   smode.mode = VT_AUTO;
   ioctl(0, VT_SETMODE, );
@@ -176,7 +177,7 @@ VGLInit(int mode)
   if (VGLDisplay == NULL)
 return -2;
 
-  if (ioctl(0, KDENABIO, 0)) {
+  if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT && ioctl(0, KDENABIO, 0)) {
 free(VGLDisplay);
 return -3;
   }
@@ -370,7 +371,8 @@ VGLCheckSwitch()
 
 VGLSwitchPending = 0;
 if (VGLOnDisplay) {
-  ioctl(0, KDENABIO, 0);
+  if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT)
+ioctl(0, KDENABIO, 0);
   ioctl(0, KDSETMODE, KD_GRAPHICS);
   ioctl(0, VGLMode, 0);
   VGLCurWindow = 0;
@@ -531,7 +533,8 @@ VGLCheckSwitch()
   munmap(VGLDisplay->Bitmap, VGLAdpInfo.va_window_size);
   ioctl(0, VGLOldMode, 0);
   ioctl(0, KDSETMODE, KD_TEXT);
-  ioctl(0, KDDISABIO, 0);
+  if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT)
+ioctl(0, KDDISABIO, 0);
   ioctl(0, VT_RELDISP, VT_TRUE);
   VGLDisplay->Bitmap = VGLBuf;
   VGLDisplay->Type = MEMBUF;

Modified: head/lib/libvgl/mouse.c
==
--- head/lib/libvgl/mouse.c Sat Apr 20 17:16:36 2019(r346453)
+++ head/lib/libvgl/mouse.c Sat Apr 20 20:29:03 2019(r346454)
@@ -111,10 +111,12 @@ VGLMousePointerShow()
   if (!VGLMouseVisible) {
 INTOFF();
 VGLMouseVisible = 1;
-crtcidx = inb(0x3c4);
-crtcval = inb(0x3c5);
-gdcidx = inb(0x3ce);
-gdcval = inb(0x3cf);
+if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) {
+  crtcidx = inb(0x3c4);
+  crtcval = inb(0x3c5);
+  gdcidx = inb(0x3ce);
+  gdcval = inb(0x3cf);
+}
 __VGLBitmapCopy(VGLDisplay, VGLMouseXpos, VGLMouseYpos, 
  , 0, 0, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
 bcopy(VGLMouseSave.Bitmap, buffer.Bitmap,
@@ -128,10 +130,12 @@ VGLMousePointerShow()
   }
 __VGLBitmapCopy(, 0, 0, VGLDisplay, 
  VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
-outb(0x3c4, crtcidx);
-outb(0x3c5, crtcval);
-outb(0x3ce, gdcidx);
-outb(0x3cf, gdcval);
+if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) {
+  outb(0x3c4, crtcidx);
+  outb(0x3c5, crtcval);
+  outb(0x3ce, gdcidx);
+  outb(0x3cf, gdcval);
+}
 INTON();
   }
 }
@@ -144,16 +148,20 @@ VGLMousePointerHide()
   if (VGLMouseVisible) {
 INTOFF();
 VGLMouseVisible = 0;
-crtcidx = inb(0x3c4);
-crtcval = inb(0x3c5);
-gdcidx = inb(0x3ce);
-gdcval = inb(0x3cf);
+if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) {
+  crtcidx = inb(0x3c4);
+  crtcval = inb(0x3c5);
+  gdcidx = inb(0x3ce);
+  gdcval = inb(0x3cf);
+}
 __VGLBitmapCopy(, 0, 0, VGLDisplay, 
  VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
-outb(0x3c4, crtcidx);
-outb(0x3c5, crtcval);
-outb(0x3ce, gdcidx);
-outb(0x3cf, gdcval);
+if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) {
+  outb(0x3c4, crtcidx);
+  outb(0x3c5, crtcval);
+  outb(0x3ce, gdcidx);
+  outb(0x3cf, gdcval);
+}
 INTON();
   }
 }

Modified: head/lib/libvgl/simple.c
==
--- head/lib/libvgl/simple.cSat Apr 20 17:16:36 2019(r346453)
+++ head/lib/libvgl/simple.cSat Apr 20 20:29:03 2019

svn commit: r346416 - head/lib/libvgl

2019-04-19 Thread Bruce Evans
Author: bde
Date: Fri Apr 19 20:29:49 2019
New Revision: 346416
URL: https://svnweb.freebsd.org/changeset/base/346416

Log:
  Fix copying of overlapping bitmaps.  The cases of copying within the
  screen bitmap and within a single MEMBUF were broken when first source
  line is before the first destination line and the sub-bitmaps overlap.
  
  The fix just copies horizontal lines in reverse order when the first
  source line is before the first destination line.  This switches
  directions unnecessarily in some cases, but the switch is about as
  fast as doing a precise detection of overlaps.  When the first lines
  are the same, there can be undetected overlap in the horizontal
  direction.  The old code already handles this mostly accidentally by
  using bcopy() for MEMBUFs and by copying through a temporary buffer
  for the screen bitmap although the latter is sub-optimal in direct
  modes.

Modified:
  head/lib/libvgl/bitmap.c

Modified: head/lib/libvgl/bitmap.c
==
--- head/lib/libvgl/bitmap.cFri Apr 19 20:23:39 2019(r346415)
+++ head/lib/libvgl/bitmap.cFri Apr 19 20:29:49 2019(r346416)
@@ -269,7 +269,7 @@ int
 __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
  VGLBitmap *dst, int dstx, int dsty, int width, int hight)
 {
-  int srcline, dstline;
+  int srcline, dstline, yend, yextra, ystep;
 
   if (srcx>src->VXsize || srcy>src->VYsize
|| dstx>dst->VXsize || dsty>dst->VYsize)
@@ -296,8 +296,17 @@ __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
  hight=dst->VYsize-dsty;
   if (width < 0 || hight < 0)
  return -1;
+  yend = srcy + hight;
+  yextra = 0;
+  ystep = 1;
+  if (src->Bitmap == dst->Bitmap && srcy < dsty) {
+yend = srcy;
+yextra = hight - 1;
+ystep = -1;
+  }
   if (src->Type == MEMBUF) {
-for (srcline=srcy, dstline=dsty; srclineBitmap+(srcline*src->VXsize+srcx)*dst->PixelBytes);
 }
@@ -319,7 +328,8 @@ __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
 } else {
   p = buffer;
 }
-for (srcline=srcy, dstline=dsty; srclinehttps://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346280 - head/lib/libvgl

2019-04-16 Thread Bruce Evans
Author: bde
Date: Tue Apr 16 15:52:04 2019
New Revision: 346280
URL: https://svnweb.freebsd.org/changeset/base/346280

Log:
  Sigh, r346279 was also a test version with the reduced size doubled (so
  it was actually double the full size in current kernels where the reduction
  is null, so overran the mmapped() buffer).

Modified:
  head/lib/libvgl/main.c

Modified: head/lib/libvgl/main.c
==
--- head/lib/libvgl/main.c  Tue Apr 16 15:41:45 2019(r346279)
+++ head/lib/libvgl/main.c  Tue Apr 16 15:52:04 2019(r346280)
@@ -275,7 +275,7 @@ VGLInit(int mode)
* get the same efficiency and bugs for all kernels.
*/
   if (VGLModeInfo.vi_mode >= M_VESA_BASE)
-VGLBufSize = 2*VGLAdpInfo.va_line_width*VGLModeInfo.vi_height*
+VGLBufSize = VGLAdpInfo.va_line_width*VGLModeInfo.vi_height*
  VGLModeInfo.vi_planes;
   VGLBuf = malloc(VGLBufSize);
   if (VGLBuf == NULL) {
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


  1   2   3   4   5   6   7   8   9   10   >