Comparison of atomic variables in C











up vote
0
down vote

favorite












I have 2 atomic variables:



atomic_ulong overwrap_cnt = 0;
atomic_ulong overwrap_read_cnt = 0;


One thread does the increasing of overwrap_cnt (once):



overwrap_cnt++;


Another thread does the comparison in an endless loop:



while(1)
{
if (overwrap_read_cnt == overwrap_cnt)
{
printf("or:%lu, ow:%lu n",overwrap_read_cnt, overwrap_cnt);
}
usleep(100000);
}


However, the result is always the following:



or:0, ow:1
or:0, ow:1
or:0, ow:1


Somehow during the comparison the variables were equal, but when we printf them - we see that they are different. The result is the same for every iteration.



Can't I compare atomic variables like this? Or what is wrong?



It's on centos 7.5 with gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)



Thanks.










share|improve this question
























  • what type is atomic_ulong ?
    – Kamil Cuk
    Nov 14 at 23:05






  • 5




    I think you'll need to wrap the entire if statement (and the increment) in protection. Your variables are individually atomic, but they are accessed twice in the if statement,, once for the comparison, again for the printf. They are locked down individually during each of those reads, but in between the comparison and the printf, the other thread could sneak in and increment overwrap_cnt
    – yano
    Nov 14 at 23:07












  • @KamilCuk something like typedef _Atomic unsigned long atomic_ulong, it is defined in stdatomic.h
    – LWimsey
    Nov 14 at 23:08










  • Och indeed, sorry.
    – Kamil Cuk
    Nov 14 at 23:09










  • Well, have you tried using atomic_store(&overwrap_cnt, atomic_load(&overwrap_cnt) + 1) and if (atomic_load(&...) == atomic_load(&...)) and so on?
    – Kamil Cuk
    Nov 14 at 23:17















up vote
0
down vote

favorite












I have 2 atomic variables:



atomic_ulong overwrap_cnt = 0;
atomic_ulong overwrap_read_cnt = 0;


One thread does the increasing of overwrap_cnt (once):



overwrap_cnt++;


Another thread does the comparison in an endless loop:



while(1)
{
if (overwrap_read_cnt == overwrap_cnt)
{
printf("or:%lu, ow:%lu n",overwrap_read_cnt, overwrap_cnt);
}
usleep(100000);
}


However, the result is always the following:



or:0, ow:1
or:0, ow:1
or:0, ow:1


Somehow during the comparison the variables were equal, but when we printf them - we see that they are different. The result is the same for every iteration.



Can't I compare atomic variables like this? Or what is wrong?



It's on centos 7.5 with gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)



Thanks.










share|improve this question
























  • what type is atomic_ulong ?
    – Kamil Cuk
    Nov 14 at 23:05






  • 5




    I think you'll need to wrap the entire if statement (and the increment) in protection. Your variables are individually atomic, but they are accessed twice in the if statement,, once for the comparison, again for the printf. They are locked down individually during each of those reads, but in between the comparison and the printf, the other thread could sneak in and increment overwrap_cnt
    – yano
    Nov 14 at 23:07












  • @KamilCuk something like typedef _Atomic unsigned long atomic_ulong, it is defined in stdatomic.h
    – LWimsey
    Nov 14 at 23:08










  • Och indeed, sorry.
    – Kamil Cuk
    Nov 14 at 23:09










  • Well, have you tried using atomic_store(&overwrap_cnt, atomic_load(&overwrap_cnt) + 1) and if (atomic_load(&...) == atomic_load(&...)) and so on?
    – Kamil Cuk
    Nov 14 at 23:17













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I have 2 atomic variables:



atomic_ulong overwrap_cnt = 0;
atomic_ulong overwrap_read_cnt = 0;


One thread does the increasing of overwrap_cnt (once):



overwrap_cnt++;


Another thread does the comparison in an endless loop:



while(1)
{
if (overwrap_read_cnt == overwrap_cnt)
{
printf("or:%lu, ow:%lu n",overwrap_read_cnt, overwrap_cnt);
}
usleep(100000);
}


However, the result is always the following:



or:0, ow:1
or:0, ow:1
or:0, ow:1


Somehow during the comparison the variables were equal, but when we printf them - we see that they are different. The result is the same for every iteration.



Can't I compare atomic variables like this? Or what is wrong?



It's on centos 7.5 with gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)



Thanks.










share|improve this question















I have 2 atomic variables:



atomic_ulong overwrap_cnt = 0;
atomic_ulong overwrap_read_cnt = 0;


One thread does the increasing of overwrap_cnt (once):



overwrap_cnt++;


Another thread does the comparison in an endless loop:



while(1)
{
if (overwrap_read_cnt == overwrap_cnt)
{
printf("or:%lu, ow:%lu n",overwrap_read_cnt, overwrap_cnt);
}
usleep(100000);
}


However, the result is always the following:



or:0, ow:1
or:0, ow:1
or:0, ow:1


Somehow during the comparison the variables were equal, but when we printf them - we see that they are different. The result is the same for every iteration.



Can't I compare atomic variables like this? Or what is wrong?



It's on centos 7.5 with gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)



Thanks.







c linux gcc atomic glibc






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 at 23:38









tink

5,84732532




5,84732532










asked Nov 14 at 22:54









pulse

549




549












  • what type is atomic_ulong ?
    – Kamil Cuk
    Nov 14 at 23:05






  • 5




    I think you'll need to wrap the entire if statement (and the increment) in protection. Your variables are individually atomic, but they are accessed twice in the if statement,, once for the comparison, again for the printf. They are locked down individually during each of those reads, but in between the comparison and the printf, the other thread could sneak in and increment overwrap_cnt
    – yano
    Nov 14 at 23:07












  • @KamilCuk something like typedef _Atomic unsigned long atomic_ulong, it is defined in stdatomic.h
    – LWimsey
    Nov 14 at 23:08










  • Och indeed, sorry.
    – Kamil Cuk
    Nov 14 at 23:09










  • Well, have you tried using atomic_store(&overwrap_cnt, atomic_load(&overwrap_cnt) + 1) and if (atomic_load(&...) == atomic_load(&...)) and so on?
    – Kamil Cuk
    Nov 14 at 23:17


















  • what type is atomic_ulong ?
    – Kamil Cuk
    Nov 14 at 23:05






  • 5




    I think you'll need to wrap the entire if statement (and the increment) in protection. Your variables are individually atomic, but they are accessed twice in the if statement,, once for the comparison, again for the printf. They are locked down individually during each of those reads, but in between the comparison and the printf, the other thread could sneak in and increment overwrap_cnt
    – yano
    Nov 14 at 23:07












  • @KamilCuk something like typedef _Atomic unsigned long atomic_ulong, it is defined in stdatomic.h
    – LWimsey
    Nov 14 at 23:08










  • Och indeed, sorry.
    – Kamil Cuk
    Nov 14 at 23:09










  • Well, have you tried using atomic_store(&overwrap_cnt, atomic_load(&overwrap_cnt) + 1) and if (atomic_load(&...) == atomic_load(&...)) and so on?
    – Kamil Cuk
    Nov 14 at 23:17
















what type is atomic_ulong ?
– Kamil Cuk
Nov 14 at 23:05




what type is atomic_ulong ?
– Kamil Cuk
Nov 14 at 23:05




5




5




I think you'll need to wrap the entire if statement (and the increment) in protection. Your variables are individually atomic, but they are accessed twice in the if statement,, once for the comparison, again for the printf. They are locked down individually during each of those reads, but in between the comparison and the printf, the other thread could sneak in and increment overwrap_cnt
– yano
Nov 14 at 23:07






I think you'll need to wrap the entire if statement (and the increment) in protection. Your variables are individually atomic, but they are accessed twice in the if statement,, once for the comparison, again for the printf. They are locked down individually during each of those reads, but in between the comparison and the printf, the other thread could sneak in and increment overwrap_cnt
– yano
Nov 14 at 23:07














@KamilCuk something like typedef _Atomic unsigned long atomic_ulong, it is defined in stdatomic.h
– LWimsey
Nov 14 at 23:08




@KamilCuk something like typedef _Atomic unsigned long atomic_ulong, it is defined in stdatomic.h
– LWimsey
Nov 14 at 23:08












Och indeed, sorry.
– Kamil Cuk
Nov 14 at 23:09




Och indeed, sorry.
– Kamil Cuk
Nov 14 at 23:09












Well, have you tried using atomic_store(&overwrap_cnt, atomic_load(&overwrap_cnt) + 1) and if (atomic_load(&...) == atomic_load(&...)) and so on?
– Kamil Cuk
Nov 14 at 23:17




Well, have you tried using atomic_store(&overwrap_cnt, atomic_load(&overwrap_cnt) + 1) and if (atomic_load(&...) == atomic_load(&...)) and so on?
– Kamil Cuk
Nov 14 at 23:17












1 Answer
1






active

oldest

votes

















up vote
0
down vote













Although the variables are individually atomic, your comparison loop is not. Perhaps counter-intuitively, reading an atomic variable may generate more instructions than reading a non-atomic.



Consider for example if you had written code with the same behavior using GCC's atomic builtins:



while(1)
{
unsigned long _tmp1 = __atomic_load_n(&overwrap_read_cnt, __ATOMIC_RELAXED);
unsigned long _tmp2 = __atomic_load_n(&overwrap_cnt, __ATOMIC_RELAXED);
if (_tmp1 == _tmp2)
{
_tmp2 = __atomic_load_n(&overwrap_cnt, __ATOMIC_RELAXED);
_tmp1 = __atomic_load_n(&overwrap_read_cnt, __ATOMIC_RELAXED);
printf("or:%lu, ow:%lu n", _tmp1, _tmp2);
}
usleep(100000);
}


Although the values fetched for the comparison were determined to be equal, they may no longer be at the time they're fetched again for the printf call.



If you want to ensure the values used later are the same as those in the if statement, you should fetch them only once, and then use the cached values throughout the rest of the loop iteration.






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53309942%2fcomparison-of-atomic-variables-in-c%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote













    Although the variables are individually atomic, your comparison loop is not. Perhaps counter-intuitively, reading an atomic variable may generate more instructions than reading a non-atomic.



    Consider for example if you had written code with the same behavior using GCC's atomic builtins:



    while(1)
    {
    unsigned long _tmp1 = __atomic_load_n(&overwrap_read_cnt, __ATOMIC_RELAXED);
    unsigned long _tmp2 = __atomic_load_n(&overwrap_cnt, __ATOMIC_RELAXED);
    if (_tmp1 == _tmp2)
    {
    _tmp2 = __atomic_load_n(&overwrap_cnt, __ATOMIC_RELAXED);
    _tmp1 = __atomic_load_n(&overwrap_read_cnt, __ATOMIC_RELAXED);
    printf("or:%lu, ow:%lu n", _tmp1, _tmp2);
    }
    usleep(100000);
    }


    Although the values fetched for the comparison were determined to be equal, they may no longer be at the time they're fetched again for the printf call.



    If you want to ensure the values used later are the same as those in the if statement, you should fetch them only once, and then use the cached values throughout the rest of the loop iteration.






    share|improve this answer

























      up vote
      0
      down vote













      Although the variables are individually atomic, your comparison loop is not. Perhaps counter-intuitively, reading an atomic variable may generate more instructions than reading a non-atomic.



      Consider for example if you had written code with the same behavior using GCC's atomic builtins:



      while(1)
      {
      unsigned long _tmp1 = __atomic_load_n(&overwrap_read_cnt, __ATOMIC_RELAXED);
      unsigned long _tmp2 = __atomic_load_n(&overwrap_cnt, __ATOMIC_RELAXED);
      if (_tmp1 == _tmp2)
      {
      _tmp2 = __atomic_load_n(&overwrap_cnt, __ATOMIC_RELAXED);
      _tmp1 = __atomic_load_n(&overwrap_read_cnt, __ATOMIC_RELAXED);
      printf("or:%lu, ow:%lu n", _tmp1, _tmp2);
      }
      usleep(100000);
      }


      Although the values fetched for the comparison were determined to be equal, they may no longer be at the time they're fetched again for the printf call.



      If you want to ensure the values used later are the same as those in the if statement, you should fetch them only once, and then use the cached values throughout the rest of the loop iteration.






      share|improve this answer























        up vote
        0
        down vote










        up vote
        0
        down vote









        Although the variables are individually atomic, your comparison loop is not. Perhaps counter-intuitively, reading an atomic variable may generate more instructions than reading a non-atomic.



        Consider for example if you had written code with the same behavior using GCC's atomic builtins:



        while(1)
        {
        unsigned long _tmp1 = __atomic_load_n(&overwrap_read_cnt, __ATOMIC_RELAXED);
        unsigned long _tmp2 = __atomic_load_n(&overwrap_cnt, __ATOMIC_RELAXED);
        if (_tmp1 == _tmp2)
        {
        _tmp2 = __atomic_load_n(&overwrap_cnt, __ATOMIC_RELAXED);
        _tmp1 = __atomic_load_n(&overwrap_read_cnt, __ATOMIC_RELAXED);
        printf("or:%lu, ow:%lu n", _tmp1, _tmp2);
        }
        usleep(100000);
        }


        Although the values fetched for the comparison were determined to be equal, they may no longer be at the time they're fetched again for the printf call.



        If you want to ensure the values used later are the same as those in the if statement, you should fetch them only once, and then use the cached values throughout the rest of the loop iteration.






        share|improve this answer












        Although the variables are individually atomic, your comparison loop is not. Perhaps counter-intuitively, reading an atomic variable may generate more instructions than reading a non-atomic.



        Consider for example if you had written code with the same behavior using GCC's atomic builtins:



        while(1)
        {
        unsigned long _tmp1 = __atomic_load_n(&overwrap_read_cnt, __ATOMIC_RELAXED);
        unsigned long _tmp2 = __atomic_load_n(&overwrap_cnt, __ATOMIC_RELAXED);
        if (_tmp1 == _tmp2)
        {
        _tmp2 = __atomic_load_n(&overwrap_cnt, __ATOMIC_RELAXED);
        _tmp1 = __atomic_load_n(&overwrap_read_cnt, __ATOMIC_RELAXED);
        printf("or:%lu, ow:%lu n", _tmp1, _tmp2);
        }
        usleep(100000);
        }


        Although the values fetched for the comparison were determined to be equal, they may no longer be at the time they're fetched again for the printf call.



        If you want to ensure the values used later are the same as those in the if statement, you should fetch them only once, and then use the cached values throughout the rest of the loop iteration.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 15 at 1:09









        Zrax

        1,165711




        1,165711






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53309942%2fcomparison-of-atomic-variables-in-c%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

            ComboBox Display Member on multiple fields

            Is it possible to collect Nectar points via Trainline?