More specific questions are:
* does there need to be an 'isync' instruction after the branch?
* is using the "memory" declaration too heavy handed, and should I be
telling gcc about just the memory location affected (and how do I do
this?)
* should I put __volatile for the formal parameters?
------------------------------------------------------------------
int pincrement(int* target)
{
int temp;
__asm__ __volatile (
"1: lwarx %0,0,%1\n\
addic %0,%0,1\n\
stwcx. %0,0,%1\n\
bne- 1b"
: "=&r" (temp)
: "r" (target)
: "cc", "memory"
);
return temp;
}
int pdecrement(int* target)
{
int temp;
__asm__ __volatile (
"1: lwarx %0,0,%1\n\
addic %0,%0,-1\n\
stwcx. %0,0,%1\n\
bne- 1b"
: "=&r" (temp)
: "r" (target)
: "cc", "memory"
);
return temp;
}
int pexchange(int* target, int value)
{
int temp;
__asm__ __volatile (
"1: lwarx %1,0,%2\n\
stwcx. %0,0,%2\n\
bne- 1b"
: "=&r" (value), "=&r" (temp)
: "r" (target)
: "cc", "memory"
);
return temp;
}
void* pexchange(void** target, void* value)
{
void* temp;
__asm__ __volatile (
"1: lwarx %1,0,%2\n\
stwcx. %0,0,%2\n\
bne- 1b"
: "=&r" (value), "=&r" (temp)
: "r" (target)
: "cc", "memory"
);
return temp;
}
------------------------------------------------------------------
Thanks,
--
Hovik Melikyan
Seems to be working on uniprocessor? That's sort of "accidental
phenomenon", believe me. GCC (other compilers aside for a moment)
doesn't offer any really meaningful mechanisms to achieve proper
memory synchronization, unfortunately. You just pray that it
wont reorder [due to lack of sophisticated optimizations] in ways
you don't want it to. "Note: Even a volatile asm instruction can
be moved in ways that appear insignificant to the compiler".
http://groups.google.com/groups?selm=3EC89A24.C4EAA4C4%40web.de
> The main question is: how to make it SMP-safe?
>
> More specific questions are:
> * does there need to be an 'isync' instruction after the branch?
That depends.
> * is using the "memory" declaration too heavy handed, and should I be
> telling gcc about just the memory location affected (and how do I do
> this?)
Try talking to gcc folks. Compilers shall understand for following:
struct msync {
enum hlb_t { hlb }; // hoist-load barrier
enum ddhlb_t { ddhlb }; // hoist-load barrier with data-dependency "hint"
enum hsb_t { hsb }; // hoist-store barrier
enum slb_t { slb }; // sink-load barrier
enum ddslb_t { ddslb }; // sink-load barrier with data-dependency "hint"
enum ssb_t { ssb }; // sink-store barrier
enum acq_t { acq }; // hoist-load + hoist-store barrier
enum rel_t { rel }; // sink-load + sink-store barrier
enum none_t { none }; // naked
};
"at least". Well, take a look at:
http://groups.google.com/groups?selm=3D60D039.DF2B7C42%40web.de
http://groups.google.com/groups?selm=3EBBE66B.98885A41%40web.de
http://www.terekhov.de/pthread_refcount_t/experimental/refcount.cpp
regards,
alexander.