Hi, Peter

On 2019/4/15 20:46, Peter Zijlstra wrote:

I write a demo about this, which I described it as overflow.

#cat test.c

//test.c
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <assert.h>

int main(void)
{
    long a = 1048576 * 9144968455305; /* shares = tg_shares * load */
    unsigned long b = a;
    //unsigned long e = 1048576 * 9144968455305;

    printf("LONG_MAX = %ld, 0x%lx\n", LONG_MAX, LONG_MAX);
    printf("ULONG_MAX = %lu, 0x%lx\n", ULONG_MAX, ULONG_MAX);

    if (b > LONG_MAX)
        printf("==overflow!!!==\n");   // OVERFLOW
    printf("a = %20ld,0x%016lx\n", a, a);
    printf("b = %20lu,0x%016lx\n", b, b);

    /* shares /= tg_weight */
    printf("a/3 = 0x%016lx\n", (a / 3));                        // WRONG
    printf("a/3 = 0x%016lx\n", (((unsigned long)a) / 3));   // unsigned
    printf("a/3 = 0x%016lx\n", (a / (unsigned long)3));    // unsigned
    printf("b/3 = 0x%016lx\n", b / 3);            // unsigned

    return EXIT_SUCCESS;
}



#./test

LONG_MAX = 9223372036854775807, 0x7fffffffffffffff
ULONG_MAX = 18446744073709551615, 0xffffffffffffffff
==overflow!!!==
a = -8857549630719655936,0x8513a98a48900000
b =  9589194442989895680,0x8513a98a48900000
a/3 = 0xd7068dd8c2daaaab     //  WRONG
a/3 = 0x2c5be32e18300000
a/3 = 0x2c5be32e18300000
b/3 = 0x2c5be32e18300000



On Sat, Apr 13, 2019 at 03:32:34AM +0000, Cheng Jian wrote:
group_share and group_runnable are tracked as 'unsigned long',
however some functions using them as 'long' which is ultimately
assigned back to 'unsigned long' variables in reweight_entity.

Since there is not scope on using a different and signed type,
this change improves code consistency and avoids further type
conversions. More important, to prevent undefined behavior
caused by overflow.
There is no undefined behaviour due to overflow.UBSAN is broken,
upgrade to GCC8 or later.

.


So, function calc_group_shares will return the wrong value.


```cpp

static long calc_group_shares(struct cfs_rq *cfs_rq)
{

    // ......

    shares = (tg_shares * load);
    if (tg_weight)
        shares /= tg_weight;
}

```


The same to calc_group_runnable.


Thanks.

    CHENG Jian.


Reply via email to