Apurva P
|
atomic_read() equivalent mechanism in QNX
|
Apurva P
10/26/2010 10:54 AM
post72428
|
atomic_read() equivalent mechanism in QNX
Hello friends,
I am using atomic operations provided by the QNX to change and access (or check) variable value between two threads...
Here is pseudo implementation of my case.
volatile unsigned digit;
thread_1()
{
while(1) {
if(digit > 10)
break;
else
....
}
...
}
thread_2()
{
while(1) {
delay(10);
atomic_add(&digit, 1);
}
...
}
Now, As far as I know there isn't any function (like atomic_read() in Linux) to read and then test variable atomically
which I can use for checking "digit" value in "If statement" in thread_1.
So, please anyone tell me, is it enough what I have done in above case or do I have to use other synchronization
mechanism like mutex or spinlock?
Thank you very much
Apurva
|
|
|
Oleh Derevenko(deleted)
|
Re: atomic_read() equivalent mechanism in QNX
|
Oleh Derevenko(deleted)
10/26/2010 12:06 PM
post72455
|
Re: atomic_read() equivalent mechanism in QNX
For the example provided you do not need atomic operations. You need them neither for reading nor for writing as there
is just one thread writing and and anoth one thread reading and value being read may be safely re-read many times. :)
Well, if also depends on the contents of 'else' clause of readed function as it may allow (or may not) the compiler to
optimize entire function out completely.
If you still want to bother yourself with atomics ;) look at
#include _NTO_CPU_HDR_(smpxchg.h)
and find
int _smp_cmpxchg(volatile unsigned *__dst, unsigned __cmp, unsigned __new);
int _smp_xchg(volatile unsigned *__dst, unsigned __src);
in it.
|
|
|
Oleh Derevenko(deleted)
|
Re: atomic_read() equivalent mechanism in QNX
|
Oleh Derevenko(deleted)
10/26/2010 12:09 PM
post72457
|
Re: atomic_read() equivalent mechanism in QNX
Also, you can always use atomic_add_value(&var, 0) for the same purpose if you do not want to dig in system includes.
> For the example provided you do not need atomic operations. You need them
> neither for reading nor for writing as there is just one thread writing and
> and anoth one thread reading and value being read may be safely re-read many
> times. :)
> Well, if also depends on the contents of 'else' clause of readed function as
> it may allow (or may not) the compiler to optimize entire function out
> completely.
>
> If you still want to bother yourself with atomics ;) look at
> #include _NTO_CPU_HDR_(smpxchg.h)
> and find
> int _smp_cmpxchg(volatile unsigned *__dst, unsigned __cmp, unsigned __new);
> int _smp_xchg(volatile unsigned *__dst, unsigned __src);
> in it.
|
|
|
Apurva P
|
Re: atomic_read() equivalent mechanism in QNX
|
Apurva P
10/27/2010 1:48 AM
post72577
|
Re: atomic_read() equivalent mechanism in QNX
> Also, you can always use atomic_add_value(&var, 0) for the same purpose if you do not want to dig in system includes.
>
> > For the example provided you do not need atomic operations. You need them
> > neither for reading nor for writing as there is just one thread writing and
> > and anoth one thread reading and value being read may be safely re-read many
> > times. :)
> > Well, if also depends on the contents of 'else' clause of readed function as
> > it may allow (or may not) the compiler to optimize entire function out
> > completely.
> >
> > If you still want to bother yourself with atomics ;) look at
> > #include _NTO_CPU_HDR_(smpxchg.h)
> > and find
> > int _smp_cmpxchg(volatile unsigned *__dst, unsigned __cmp, unsigned __new);
> > int _smp_xchg(volatile unsigned *__dst, unsigned __src);
> > in it.
>
>
Thanks Oleh for quick reply.
Using atomic_add_value(&var, 0) is certainly a solution to read value of a variable atomically.
But, as you said value may be safely re-read many times without using any atomic function... I am just wondering, why is
there function atomic_read() in Linux to "Read" value atomically?
Thanks
Apurva
|
|
|
Oleh Derevenko(deleted)
|
Re: atomic_read() equivalent mechanism in QNX
|
Oleh Derevenko(deleted)
10/27/2010 3:20 AM
post72578
|
Re: atomic_read() equivalent mechanism in QNX
> Using atomic_add_value(&var, 0) is certainly a solution to read value of a
> variable atomically.
>
> But, as you said value may be safely re-read many times without using any
> atomic function... I am just wondering, why is there function atomic_read() in
> Linux to "Read" value atomically?
>
My answer in no meaning pretends to be authoritative but my personal impression is that in application programming with
proper algorithm structure, with proper coding and proper data alignment only write needs to be atomic. Atomic reads
could be necessary only for low level programming if a variable is queried in a loop without a delay (in spin style).
And even in those rare cases atomic read would be used it is more intended is to combine memory fencing instruction with
reading in a single operation rather than provide atomicity. For a properly aligned variable both reading and writing
are atomic even without any special means.
|
|
|
Armin Steinhoff
|
Re: atomic_read() equivalent mechanism in QNX
|
Armin Steinhoff
10/27/2010 3:29 AM
post72580
|
Re: atomic_read() equivalent mechanism in QNX
Oleh Derevenko wrote:
>> Using atomic_add_value(&var, 0) is certainly a solution to read value of a
>> variable atomically.
>>
>> But, as you said value may be safely re-read many times without using any
>> atomic function... I am just wondering, why is there function atomic_read() in
>> Linux to "Read" value atomically?
>>
> My answer in no meaning pretends to be authoritative but my personal impression is that in application programming
with proper algorithm structure, with proper coding and proper data alignment only write needs to be atomic.
No ... there are a lot of cases where atomic read is necessary. The
simplest case is reading a 32bit variable which is constantly updated by
second task ... and this happens not only in low level code.
--Armin
> Atomic reads could be necessary only for low level programming if a variable is queried in a loop without a delay
(in spin style). And even in those rare cases atomic read would be used it is more intended is to combine memory fencing
instruction with reading in a single operation rather than provide atomicity. For a properly aligned variable both
reading and writing are atomic even without any special means.
>
>
>
> _______________________________________________
>
> OSTech
> http://community.qnx.com/sf/go/post72578
>
>
|
|
|
Oleh Derevenko(deleted)
|
Re: atomic_read() equivalent mechanism in QNX
|
Oleh Derevenko(deleted)
10/27/2010 3:46 AM
post72581
|
Re: atomic_read() equivalent mechanism in QNX
> > My answer in no meaning pretends to be authoritative but my personal
> impression is that in application programming with proper algorithm structure,
> with proper coding and proper data alignment only write needs to be atomic.
>
>
> No ... there are a lot of cases where atomic read is necessary. The
> simplest case is reading a 32bit variable which is constantly updated by
> second task ... and this happens not only in low level code.
>
Well, and what about that? Let it be updated as frequently as it would like. Anyway, if you do a simple memory read or
you do locked cmpxchg you'll get the same result. Memory access within a single cache line is atimic by default. Just
simply reading a memory variable and taking no other actions is senseless with no regard to which reading method you use
. The atomic operation usage is always related to code executed before it or code that is going to follow it. And
atomicity for pure reading could only be used to provide separation and synchronization with neighbour code, not for the
reading operation itself.
|
|
|
Armin Steinhoff
|
Re: atomic_read() equivalent mechanism in QNX
|
Armin Steinhoff
10/27/2010 6:00 AM
post72590
|
Re: atomic_read() equivalent mechanism in QNX
Oleh Derevenko wrote:
>>> My answer in no meaning pretends to be authoritative but my personal
>> impression is that in application programming with proper algorithm structure,
>> with proper coding and proper data alignment only write needs to be atomic.
>>
>>
>> No ... there are a lot of cases where atomic read is necessary. The
>> simplest case is reading a 32bit variable which is constantly updated by
>> second task ... and this happens not only in low level code.
>>
> Well, and what about that? Let it be updated as frequently as it would like. Anyway, if you do a simple memory read or
you do locked cmpxchg you'll get the same result. Memory access within a single cache line is atimic by default. Just
simply reading a memory variable and taking no other actions is senseless with no regard to which reading method you use
. The atomic operation usage is always related to code executed before it or code that is going to follow it. And
atomicity for pure reading could only be used to provide separation and synchronization with neighbour code, not for the
reading operation itself.
We are not talking about assembler code. The motivation to use an
atomic_read in C code is about concurrency!
--Armin
>
>
> _______________________________________________
>
> OSTech
> http://community.qnx.com/sf/go/post72581
>
>
|
|
|
Aleksandar Ristovski(deleted)
|
Re: atomic_read() equivalent mechanism in QNX
|
Aleksandar Ristovski(deleted)
10/27/2010 8:35 AM
post72609
|
Re: atomic_read() equivalent mechanism in QNX
If you want it to work properly across multiple architectures, you need both.
----- Original Message -----
From: Oleh Derevenko [mailto:community-noreply@qnx.com]
Sent: Wednesday, October 27, 2010 03:46 AM
To: ostech-core_os <post72581@community.qnx.com>
Subject: Re: atomic_read() equivalent mechanism in QNX
> > My answer in no meaning pretends to be authoritative but my personal
> impression is that in application programming with proper algorithm structure,
> with proper coding and proper data alignment only write needs to be atomic.
>
>
> No ... there are a lot of cases where atomic read is necessary. The
> simplest case is reading a 32bit variable which is constantly updated by
> second task ... and this happens not only in low level code.
>
Well, and what about that? Let it be updated as frequently as it would like. Anyway, if you do a simple memory read or
you do locked cmpxchg you'll get the same result. Memory access within a single cache line is atimic by default. Just
simply reading a memory variable and taking no other actions is senseless with no regard to which reading method you use
. The atomic operation usage is always related to code executed before it or code that is going to follow it. And
atomicity for pure reading could only be used to provide separation and synchronization with neighbour code, not for the
reading operation itself.
_______________________________________________
OSTech
http://community.qnx.com/sf/go/post72581
|
|
|
Oleh Derevenko(deleted)
|
Re: atomic_read() equivalent mechanism in QNX
|
Oleh Derevenko(deleted)
10/27/2010 8:43 AM
post72611
|
Re: atomic_read() equivalent mechanism in QNX
Sure, I know, I need atomic function for code to work the same way on all the architectures. But I'm just saying that
atomic_read() is atomic not because the simple assignment operator would not be atomic without it, but rather to aid
synchronization with other memory access operations.
That is,
res = atomic_read(&val);
could always be safely replaced with sequence
__cpu_membarrier();
res = val;
> If you want it to work properly across multiple architectures, you need both.
>
>
> ----- Original Message -----
> From: Oleh Derevenko [mailto:community-noreply@qnx.com]
> Sent: Wednesday, October 27, 2010 03:46 AM
> To: ostech-core_os <post72581@community.qnx.com>
> Subject: Re: atomic_read() equivalent mechanism in QNX
>
> > > My answer in no meaning pretends to be authoritative but my personal
> > impression is that in application programming with proper algorithm
> structure,
> > with proper coding and proper data alignment only write needs to be atomic.
>
> >
> >
> > No ... there are a lot of cases where atomic read is necessary. The
> > simplest case is reading a 32bit variable which is constantly updated by
> > second task ... and this happens not only in low level code.
> >
>
> Well, and what about that? Let it be updated as frequently as it would like.
> Anyway, if you do a simple memory read or you do locked cmpxchg you'll get the
> same result. Memory access within a single cache line is atimic by default.
> Just simply reading a memory variable and taking no other actions is senseless
> with no regard to which reading method you use. The atomic operation usage is
> always related to code executed before it or code that is going to follow it.
> And atomicity for pure reading could only be used to provide separation and
> synchronization with neighbour code, not for the reading operation itself.
>
|
|
|
Oleh Derevenko(deleted)
|
Re: atomic_read() equivalent mechanism in QNX
|
Oleh Derevenko(deleted)
10/27/2010 8:48 AM
post72615
|
Re: atomic_read() equivalent mechanism in QNX
Well,
> __cpu_membarrier();
> res = *(const volatile int *)&val;
of course.
> That is,
> res = atomic_read(&val);
> could always be safely replaced with sequence
> __cpu_membarrier();
> res = val;
>
> > If you want it to work properly across multiple architectures, you need both
> .
> >
|
|
|
Oleh Derevenko(deleted)
|
Re: atomic_read() equivalent mechanism in QNX
|
Oleh Derevenko(deleted)
10/28/2010 5:25 AM
post72750
|
Re: atomic_read() equivalent mechanism in QNX
> That is,
> res = atomic_read(&var);
> could always be safely replaced with sequence
> __cpu_membarrier();
> res = *(const volatile int *)&var;
OK. If there are no objections, let's continue the explanation.
Similarly, atomic write can be substituted like this:
atomic_write(&var, src);
with
*(volatile int *)&var = src;
__cpu_membarrier();
Now, if to consider pure atomic read, there could be following possible options:
1) Memory barrier is not necessary by itself (as in orininal topic-poster's example) and atomic read could be replaced
with a simple assignment.
2) Atomic read is typically used in a bundle with atomic write like this
atomic_write(&var1, src);
res = atomic_read(&var2);
which can be expanded
*(volatile int *)&var1 = src;
__cpu_membarrier();
__cpu_membarrier();
res = *(const volatile int *)&var2;
then extra __cpu_membarrier() can be canceled
*(volatile int *)&var1 = src;
__cpu_membarrier();
res = *(const volatile int *)&var2;
and this can be wrapped back into
atomic_write(&var1, src);
res = *(const volatile int *)&var2;
which shows that with proper coding and memory alignment atomic read could be avoided altogether and is unnecessary
(note: I'm still talking about application level code where quick spin-style checks are not used).
Also keep in mind that it needs not be atomic write operation only that would contain implicit memory barrier before
reading. That could also be any mutex locking/unlocking operations, condvar waitiing, any kernel calls.
|
|
|
Armin Steinhoff
|
Re: atomic_read() equivalent mechanism in QNX
|
Armin Steinhoff
10/29/2010 4:08 AM
post72935
|
Re: atomic_read() equivalent mechanism in QNX
Oleh Derevenko wrote:
>> That is,
>> res = atomic_read(&var);
>> could always be safely replaced with sequence
>> __cpu_membarrier();
>> res = *(const volatile int *)&var;
> OK. If there are no objections, let's continue the explanation.
>
> Similarly, atomic write can be substituted like this:
> atomic_write(&var, src);
> with
> *(volatile int *)&var = src;
> __cpu_membarrier();
>
> Now, if to consider pure atomic read, there could be following possible options:
>
> 1) Memory barrier is not necessary by itself (as in orininal topic-poster's example) and atomic read could be replaced
with a simple assignment.
>
> 2) Atomic read is typically used in a bundle with atomic write like this
> atomic_write(&var1, src);
> res = atomic_read(&var2);
This make no sense ...
No one would use the atomic calls in this way, the typical use is:
Task or thread A: atomic_write(&var, src);
Task or thread B: atomic_read(&var);
--Armin
> which can be expanded
> *(volatile int *)&var1 = src;
> __cpu_membarrier();
> __cpu_membarrier();
> res = *(const volatile int *)&var2;
>
> then extra __cpu_membarrier() can be canceled
> *(volatile int *)&var1 = src;
> __cpu_membarrier();
> res = *(const volatile int *)&var2;
>
> and this can be wrapped back into
> atomic_write(&var1, src);
> res = *(const volatile int *)&var2;
>
> which shows that with proper coding and memory alignment atomic read could be avoided altogether and is unnecessary
(note: I'm still talking about application level code where quick spin-style checks are not used).
>
> Also keep in mind that it needs not be atomic write operation only that would contain implicit memory barrier before
reading. That could also be any mutex locking/unlocking operations, condvar waitiing, any kernel calls.
>
>
>
> _______________________________________________
>
> OSTech
> http://community.qnx.com/sf/go/post72750
>
>
|
|
|
Oleh Derevenko(deleted)
|
Re: atomic_read() equivalent mechanism in QNX
|
Oleh Derevenko(deleted)
10/29/2010 5:34 AM
post72937
|
Re: atomic_read() equivalent mechanism in QNX
> > 2) Atomic read is typically used in a bundle with atomic write like this
> > atomic_write(&var1, src);
> > res = atomic_read(&var2);
>
> This make no sense ...
> No one would use the atomic calls in this way, the typical use is:
>
> Task or thread A: atomic_write(&var, src);
>
> Task or thread B: atomic_read(&var);
>
Do you read what I write? Memory access within a single cache line is atomic by default. Or you can point to an
architecture where it is not the case?
You do not need atomic operations for your example at all. There may be processor caches out of sync and you'll not get
the data you are writing in other task at once but sooner or later they will get synchronized and from application level
programming's point of view few more empty loops and few more extra variable checks do not matter (if not to mention
that at application level checking a variable in a loop without delays is inacceptable way of programming at all).
|
|
|
Armin Steinhoff
|
Re: atomic_read() equivalent mechanism in QNX
|
Armin Steinhoff
10/31/2010 6:31 AM
post73084
|
Re: atomic_read() equivalent mechanism in QNX
Oleh Derevenko wrote:
>>> 2) Atomic read is typically used in a bundle with atomic write like this
>>> atomic_write(&var1, src);
>>> res = atomic_read(&var2);
>> This make no sense ...
>> No one would use the atomic calls in this way, the typical use is:
>>
>> Task or thread A: atomic_write(&var, src);
>>
>> Task or thread B: atomic_read(&var);
>>
> Do you read what I write?
Yes, but not from a cache line :)
> Memory access within a single cache line is atomic by default. Or you can point to an architecture where it is not the
case?
atamic_read/write are referencing normal memory and not locations of
a CPU cache. In general not all access to memory go through the CPU cache.
So it make sense to have the atomic_read ...
--Armin
> You do not need atomic operations for your example at all. There may be processor caches out of sync and you'll not
get the data you are writing in other task at once but sooner or later they will get synchronized and from application
level programming's point of view few more empty loops and few more extra variable checks do not matter (if not to
mention that at application level checking a variable in a loop without delays is inacceptable way of programming at
all).
>
>
>
> _______________________________________________
>
> OSTech
> http://community.qnx.com/sf/go/post72937
>
>
|
|
|
|