mem_unit

Henry Cejtin henry@sourcelight.com
Sat, 16 Mar 2002 01:10:52 -0600


I  think  that thing that link with the new libraries just won't run with the
old ones.  The converse is false, but on the other  hand  the  new  libraries
might  fix  some  bugs  in  the  old  ones.  I don't think there really is an
alternative to providing both.  At  least  with  Red  Hat  the  combinatorial
explosion isn't quite so bad.  The old Red Hat has the older glibc, the older
type of RPM and the older kernel.  The newer Red Hats have the reverse.   For
other  distributions  things could be a mix-and-match, but I think that if we
provide both of these (say the old being Red Hat  6.*  based  (the  different
values  of  *  should all be mutually compatible) and the newer one being 7.*
then we should be ok.

As to the mem_unit problem and the different kernels, here is the  situation:
The  old  include  files  do not have a mem_unit field in the struct, but the
struct has some padding so its size is the  same  as  if  it  had  the  extra
fields.   This  extra  padding  is  zero'd out in the old kernels.  Hence you
have:

    Compiled with old includes, any kernel:
        no mem_unit field.
    Compiled with new includes, running on old kernel:
        mem_unit will always be 0.
    Compiled with new includes, running on new kernel:
        mem_unit will be 1 (or bigger on big-memory or big-swap machines).

One option would be to simple  include  the  struct  definition  in  our  own
include  file  (basically  from /usr/include/linux/kernel.h of a new kernel).
This way we will ALWAYS have mem_unit defined.  The code would then check  if
the  value  was  0  (meaning  it  is  running  under an old kernel) and use 1
instead.

The alternative option would be to never have the code do
    s.mem_unit
where s was of type `struct sysinfo', but instead to always do
    SI_MEMUNIT(s)
Then we would use one of 2  include  files:  if  being  compiled  on  an  new
machine, the include file would contain
    #define SI_MEMUNIT(s)   (s).mem_unit
and if being compiled on an old machine it would contain
    #define SI_MEMUNIT(s)   ((s), 1)
(The  funny right-hand-side is just so that any side effects are handled.  It
almost certainly makes no difference, but it is better to be safe and  the  C
compiler will optimize it away.)

The second approach has several disadvantages: one is that the source code no
longer reflects either option, but a new world,  which  is  a  pain  to  keep
straight.   The  second  disadvantage  is  that MLton executables made on old
systems will not run properly on big-memory machines running new kernels.

The first solution doesn't suffer from either of these, but has the  uglyness
of the struct definition being copied into our source.

For  the second solution you would need some kind of configure program to see
which include files you have.  This just involves trying to compile something
that  refers  to  the mem_unit member and seeing if it compiles successfully.
Not a big deal, but definitely another minor pain.