RE: [PATCH 3/4] bpf, docs: Use consistent names for the same field

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> On Wed, Oct 19, 2022 at 4:35 PM Stanislav Fomichev <sdf@xxxxxxxxxx>
> wrote:
> > On Wed, Oct 19, 2022 at 2:06 PM Dave Thaler <dthaler@xxxxxxxxxxxxx>
> wrote:
> > >
> > > sdf@xxxxxxxxxx wrote:
> > > > >   ``BPF_ADD | BPF_X | BPF_ALU`` means::
> > > >
> > > > > -  dst_reg = (u32) dst_reg + (u32) src_reg;
> > > > > +  dst = (u32) (dst + src)
> > > >
> > > > IIUC, by going from (u32) + (u32) to (u32)(), we want to signal
> > > > that the value will just wrap around?
> > >
> > > Right.  In particular the old line could be confusing if one
> > > misinterpreted it as saying that the addition could overflow into a
> > > higher bit.  The new line is intended to be unambiguous that the upper 32
> bits are 0.
> > >
> > > > But isn't it more confusing now because it's unclear what the sign
> > > > of the dst/src is (s32 vs u32)?
> > >
> > > As stated the upper 32 bits have to be 0, just as any other u32 assignment.
> >
> > Do we mention somewhere above/below that the operands are unsigned?
> > IOW, what prevents me from reading this new format as follows?
> >
> > dst = (u32) ((s32)dst + (s32)src)
> 
> The doc mentions it, but I completely agree with you.
> The original line was better.
> Dave, please undo this part.

Nothing prevents you from reading the new format as
    dst = (u32) ((s32)dst + (s32)src)
because that implementation wouldn't be wrong.  

Below is why, please point out any logic errors if you see any.

Mathematically, all of the following have identical results:
    dst = (u32) ((s32)dst + (s32)src)
    dst = (u32) ((u32)dst + (u32)src)
    dst = (u32) ((s32)dst + (u32)src)
    dst = (u32) ((u32)dst + (s32)src)

u32 and s32, once you allow overflow/underflow to wrap within 32 bits, are
mathematical rings (see https://en.wikipedia.org/wiki/Ring_(mathematics) )
meaning they're a circular space where X, X + 2^32, and X - 2^32 are equal.
So (s32)src == (u32)src when the most significant bit is clear, and
(s32)src == (u32)src - 2^32 when the most significant bit is set.

So the sign of the addition operands does not matter here.
What matters is whether you do addition where the result can be
more than 32 bits or not, which is what the new line makes unambiguous
and the old line did not.

Specifically, nothing prevented mis-interpreting the old line as

u64 temp = (u32)dst;
temp += (u32)src;
dst = temp; 

which would give the wrong answer since the upper 32-bits might be non-zero.

u64 temp = (s32)dst;
temp += (s32)src;
dst = (u32)temp;

Would however give the correct answer, same as

u64 temp = (u32)dst;
temp += (u32)src;
dst = (u32)temp;

As such, I maintain the old line was bad and the new line is still good.
If you like I can explicitly say
    dst = (u32) ((u32)dst + (u32)src)
but as noted above the operand sign is irrelevant once you cast the result.

Let me know if I'm missing anything.

Dave








[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux