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.
c linux gcc atomic glibc
|
show 5 more comments
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.
c linux gcc atomic glibc
what type isatomic_ulong
?
– Kamil Cuk
Nov 14 at 23:05
5
I think you'll need to wrap the entireif
statement (and the increment) in protection. Your variables are individually atomic, but they are accessed twice in theif
statement,, once for the comparison, again for theprintf
. They are locked down individually during each of those reads, but in between the comparison and theprintf
, the other thread could sneak in and incrementoverwrap_cnt
– yano
Nov 14 at 23:07
@KamilCuk something liketypedef _Atomic unsigned long atomic_ulong
, it is defined instdatomic.h
– LWimsey
Nov 14 at 23:08
Och indeed, sorry.
– Kamil Cuk
Nov 14 at 23:09
Well, have you tried usingatomic_store(&overwrap_cnt, atomic_load(&overwrap_cnt) + 1)
andif (atomic_load(&...) == atomic_load(&...))
and so on?
– Kamil Cuk
Nov 14 at 23:17
|
show 5 more comments
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.
c linux gcc atomic glibc
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
c linux gcc atomic glibc
edited Nov 14 at 23:38
tink
5,84732532
5,84732532
asked Nov 14 at 22:54
pulse
549
549
what type isatomic_ulong
?
– Kamil Cuk
Nov 14 at 23:05
5
I think you'll need to wrap the entireif
statement (and the increment) in protection. Your variables are individually atomic, but they are accessed twice in theif
statement,, once for the comparison, again for theprintf
. They are locked down individually during each of those reads, but in between the comparison and theprintf
, the other thread could sneak in and incrementoverwrap_cnt
– yano
Nov 14 at 23:07
@KamilCuk something liketypedef _Atomic unsigned long atomic_ulong
, it is defined instdatomic.h
– LWimsey
Nov 14 at 23:08
Och indeed, sorry.
– Kamil Cuk
Nov 14 at 23:09
Well, have you tried usingatomic_store(&overwrap_cnt, atomic_load(&overwrap_cnt) + 1)
andif (atomic_load(&...) == atomic_load(&...))
and so on?
– Kamil Cuk
Nov 14 at 23:17
|
show 5 more comments
what type isatomic_ulong
?
– Kamil Cuk
Nov 14 at 23:05
5
I think you'll need to wrap the entireif
statement (and the increment) in protection. Your variables are individually atomic, but they are accessed twice in theif
statement,, once for the comparison, again for theprintf
. They are locked down individually during each of those reads, but in between the comparison and theprintf
, the other thread could sneak in and incrementoverwrap_cnt
– yano
Nov 14 at 23:07
@KamilCuk something liketypedef _Atomic unsigned long atomic_ulong
, it is defined instdatomic.h
– LWimsey
Nov 14 at 23:08
Och indeed, sorry.
– Kamil Cuk
Nov 14 at 23:09
Well, have you tried usingatomic_store(&overwrap_cnt, atomic_load(&overwrap_cnt) + 1)
andif (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
|
show 5 more comments
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.
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 15 at 1:09
Zrax
1,165711
1,165711
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 theif
statement,, once for the comparison, again for theprintf
. They are locked down individually during each of those reads, but in between the comparison and theprintf
, the other thread could sneak in and incrementoverwrap_cnt
– yano
Nov 14 at 23:07
@KamilCuk something like
typedef _Atomic unsigned long atomic_ulong
, it is defined instdatomic.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)
andif (atomic_load(&...) == atomic_load(&...))
and so on?– Kamil Cuk
Nov 14 at 23:17