Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

atomic inc/dec/xchg for PowerPC

70 views
Skip to first unread message

Hovik Melikyan

unread,
Nov 5, 2003, 4:26:35 PM11/5/03
to

We need implementation of atomic increment, decrement and exchange functions
for PowerPC. Below is a rough attempt that seems to be working on
uni-processor. 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?
* 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


Alexander Terekhov

unread,
Nov 6, 2003, 6:17:20 AM11/6/03
to

Hovik Melikyan wrote:
>
> We need implementation of atomic increment, decrement and exchange functions
> for PowerPC. Below is a rough attempt that seems to be working on
> uni-processor.

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.

0 new messages