www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - help with assembler

reply Carlos Santander <csantander619 gmail.com> writes:
The following functions are part of Ben Hinkle's Locks library. I'm using GDC
on 
Mac (PPC), so assembler (especially x86 assembler) isn't supported. I don't
know 
assembly. Can somebody help me to translate them to D, please?

/////////////////////////////////////////////////////////

/** Compare the value at *expect with the value at *ptr and if
  * they agree copy *update to *ptr and return true otherwise return
  * false.
  * \param ptr the memory location to update
  * \param expect the expected value at *ptr
  * \param update the new value for *ptr
  * \return true if successful
  */
extern (C) bool compareAndSet64(void* vptr, void* expect, void* update) {
   asm {
     naked;
     enter 0,0;
     mov	EDI,update;
     mov	EBX,[EDI];
     mov	ECX,4[EDI];
     mov	EDI,expect;
     mov	EAX,[EDI];
     mov	EDX,4[EDI];
     mov	EDI,vptr;
     lock;
     cmpxch8b	 [EDI];
     setz AL;
     leave;
     ret;
   }
}


/** Compare expect to *ptr and if equal copy update to *ptr and return true;
  * Otherwise return false.
  * \param ptr the memory location to update
  * \param expect the expected value at *ptr
  * \param update the new value for *ptr
  * \return true if successful
  */
bool compareAndSet32(void* vptr, void* expect, void* update) {
   return compareAndSet32(vptr,cast(int)expect,cast(int)update);
}

// alternative declaration for data instead of pointers
extern (C) bool compareAndSet32(void* vptr, int expect, int update) {
   asm {
     naked;
     enter 0,0;
     mov	EBX,update;
     mov	EAX,expect;
     mov	ECX,vptr;
     lock;
     cmpxchg	[ECX],EBX;
     setz	AL;
     leave;
     ret;
   }
}

/** Atomically add *val with x and return original content of *value
  * \param val the value to add to
  * \param x the amount to add
  * \return the value before adding x
  */
extern (C) int atomicAdd32(int* val, int x) {
   asm {
     naked;
     enter 0,0;
     mov	EAX,x;
     mov	EBX,val;
     lock;
     xadd [EBX],EAX;
     leave;
     ret;
   }
}

/** Atomically increment *val
  * \param val the value to increment
  */
extern (C) void atomicInc32(int* val) {
   asm {
     naked;
     enter 0,0;
     mov	EBX,val;
     lock;
     inc [EBX];
     leave;
     ret;
   }
}

/** Atomically decrement *val
  * \param val the value to decrement
  */
extern (C) void atomicDec32(int* val) {
   asm {
     naked;
     enter 0,0;
     mov	EBX,val;
     lock;
     dec [EBX];
     leave;
     ret;
   }
}

/** Atomically set *val and return old value
  * \param val the value to set
  * \param newval the new value
  * \return the old value
  */
extern (C) int atomicExchange32(int* val, int newval) {
   asm {
     naked;
     enter 0,0;
     mov	EAX,newval;
     mov	EBX,val;
     xchg [EBX],EAX;
     leave;
     ret;
   }
}

/////////////////////////////////////////////////////////

-- 
Carlos Santander Bernal
Jan 26 2006
next sibling parent reply "Kris" <fu bar.com> writes:
I thought the Mac was on x86 these days :-D

Seriously though, Ben's port of Prof Lea's library uses the 
compareAndSet32() function only. Unless you have a specific (other) need, 
you can make life easier by dropping all the others.

That aside, you can convert these to D for a single processor/single core 
CPU only. Anything else requires the equivalent of a bus-lock (with that 
'lock' prefix in the assembler), which D does not support at a higher level. 
From what I recall, Ben actually had non-assembler version of these 
functions ~ ones that would work only on a single-core machine:

Yes ~ here it is:

  static bool compareAndSet32(void* vptr, int expect, int update) {
    int* vi = cast(int*)vptr;
    bool res = false;
    synchronized {
      res = expect == *vi;
      if (res) {
         *vi = update;
      }
    }
    return res;
  }

Note, again, that the above will not wok on a machine with more than one 
core, or more than one processor ~ works for multi-threads only.

Good luck;

- Kris

P.S. You might also encourage Sean to get his Atomic lib running on linux 
and the Mac :)



"Carlos Santander" <csantander619 gmail.com> wrote in message 
news:drboof$2rik$1 digitaldaemon.com...
 The following functions are part of Ben Hinkle's Locks library. I'm using 
 GDC on Mac (PPC), so assembler (especially x86 assembler) isn't supported. 
 I don't know assembly. Can somebody help me to translate them to D, 
 please?

 /////////////////////////////////////////////////////////

 /** Compare the value at *expect with the value at *ptr and if
  * they agree copy *update to *ptr and return true otherwise return
  * false.
  * \param ptr the memory location to update
  * \param expect the expected value at *ptr
  * \param update the new value for *ptr
  * \return true if successful
  */
 extern (C) bool compareAndSet64(void* vptr, void* expect, void* update) {
   asm {
     naked;
     enter 0,0;
     mov EDI,update;
     mov EBX,[EDI];
     mov ECX,4[EDI];
     mov EDI,expect;
     mov EAX,[EDI];
     mov EDX,4[EDI];
     mov EDI,vptr;
     lock;
     cmpxch8b [EDI];
     setz AL;
     leave;
     ret;
   }
 }


 /** Compare expect to *ptr and if equal copy update to *ptr and return 
 true;
  * Otherwise return false.
  * \param ptr the memory location to update
  * \param expect the expected value at *ptr
  * \param update the new value for *ptr
  * \return true if successful
  */
 bool compareAndSet32(void* vptr, void* expect, void* update) {
   return compareAndSet32(vptr,cast(int)expect,cast(int)update);
 }

 // alternative declaration for data instead of pointers
 extern (C) bool compareAndSet32(void* vptr, int expect, int update) {
   asm {
     naked;
     enter 0,0;
     mov EBX,update;
     mov EAX,expect;
     mov ECX,vptr;
     lock;
     cmpxchg [ECX],EBX;
     setz AL;
     leave;
     ret;
   }
 }

 /** Atomically add *val with x and return original content of *value
  * \param val the value to add to
  * \param x the amount to add
  * \return the value before adding x
  */
 extern (C) int atomicAdd32(int* val, int x) {
   asm {
     naked;
     enter 0,0;
     mov EAX,x;
     mov EBX,val;
     lock;
     xadd [EBX],EAX;
     leave;
     ret;
   }
 }

 /** Atomically increment *val
  * \param val the value to increment
  */
 extern (C) void atomicInc32(int* val) {
   asm {
     naked;
     enter 0,0;
     mov EBX,val;
     lock;
     inc [EBX];
     leave;
     ret;
   }
 }

 /** Atomically decrement *val
  * \param val the value to decrement
  */
 extern (C) void atomicDec32(int* val) {
   asm {
     naked;
     enter 0,0;
     mov EBX,val;
     lock;
     dec [EBX];
     leave;
     ret;
   }
 }

 /** Atomically set *val and return old value
  * \param val the value to set
  * \param newval the new value
  * \return the old value
  */
 extern (C) int atomicExchange32(int* val, int newval) {
   asm {
     naked;
     enter 0,0;
     mov EAX,newval;
     mov EBX,val;
     xchg [EBX],EAX;
     leave;
     ret;
   }
 }

 /////////////////////////////////////////////////////////

 -- 
 Carlos Santander Bernal 

Jan 26 2006
parent Sean Kelly <sean f4.ca> writes:
Kris wrote:
 I thought the Mac was on x86 these days :-D
 
 Seriously though, Ben's port of Prof Lea's library uses the 
 compareAndSet32() function only. Unless you have a specific (other) need, 
 you can make life easier by dropping all the others.
 
 That aside, you can convert these to D for a single processor/single core 
 CPU only. Anything else requires the equivalent of a bus-lock (with that 
 'lock' prefix in the assembler), which D does not support at a higher level.

While this is true for int and smaller variables on x86 systems, I'm not entirely certain it is true for longs on x86, nor may it be true for unaligned variables on non-x86 architectures--ie. anything where multiple ASM instructions may be used for a single logical operation. The x86 makes all this lock-free business unusually easy by making nearly every operation implicitly atomic. I'm not sure that the PPC is quite so forgiving.
 P.S. You might also encourage Sean to get his Atomic lib running on linux 
 and the Mac :)

It isn't Linux that's the problem so much as the PPC. But I think I could track down enough material to give it a shot, with the caveat that I won't even be able to compile it :-) Sean
Jan 26 2006
prev sibling next sibling parent reply Sean Kelly <sean f4.ca> writes:
Carlos Santander wrote:
 The following functions are part of Ben Hinkle's Locks library. I'm 
 using GDC on Mac (PPC), so assembler (especially x86 assembler) isn't 
 supported. I don't know assembly. Can somebody help me to translate them 
 to D, please?

Unfortunately, there is no perfect D equivalent. The purpose of these functions is twofold: first, there is typically a desire to impose access ordering to maintain algorithm correctness without using Mutexes, and second, to ensure that the data updates occur atomically (again, without Mutexes). Wrapping things in a 'synchronized' block should typically address the ordering issue (though it is not guaranteed as far as relevant specs on Mutexes are concerned--this is merely a common side-effect of how many Mutex implementations work), however, it can not cause the update to occur atomically. If you absolutely must use the Locks library, take my suggested code below and complement it by also only ever reading the variables pointed to by vptr while in a synchronized block. ie. int loadInt( void* vptr ) { synchronized return *cast(int*)vptr; } long loadLong( void* vptr ) { synchronized return *cast(long*)vptr; }
 /////////////////////////////////////////////////////////
 
 /** Compare the value at *expect with the value at *ptr and if
  * they agree copy *update to *ptr and return true otherwise return
  * false.
  * \param ptr the memory location to update
  * \param expect the expected value at *ptr
  * \param update the new value for *ptr
  * \return true if successful
  */
 extern (C) bool compareAndSet64(void* vptr, void* expect, void* update) {
   asm {
     naked;
     enter 0,0;
     mov    EDI,update;
     mov    EBX,[EDI];
     mov    ECX,4[EDI];
     mov    EDI,expect;
     mov    EAX,[EDI];
     mov    EDX,4[EDI];
     mov    EDI,vptr;
     lock;
     cmpxch8b     [EDI];
     setz AL;
     leave;
     ret;
   }
 }

extern (C) bool compareAndSet64(void* vptr, long expect, long update) { synchronized { if( *(cast(long*)vptr) == expect) { *(cast(long*)vptr) = update; return true; } return false; } }
 /** Compare expect to *ptr and if equal copy update to *ptr and return 
 true;
  * Otherwise return false.
  * \param ptr the memory location to update
  * \param expect the expected value at *ptr
  * \param update the new value for *ptr
  * \return true if successful
  */
 bool compareAndSet32(void* vptr, void* expect, void* update) {
   return compareAndSet32(vptr,cast(int)expect,cast(int)update);
 }
 
 // alternative declaration for data instead of pointers
 extern (C) bool compareAndSet32(void* vptr, int expect, int update) {
   asm {
     naked;
     enter 0,0;
     mov    EBX,update;
     mov    EAX,expect;
     mov    ECX,vptr;
     lock;
     cmpxchg    [ECX],EBX;
     setz    AL;
     leave;
     ret;
   }
 }

extern (C) bool compareAndSet32(void* vptr, int expect, int update) { synchronized { if( *(cast(int*)vptr) == expect) { *(cast(int*)vptr) = update; return true; } return false; } }
 /** Atomically add *val with x and return original content of *value
  * \param val the value to add to
  * \param x the amount to add
  * \return the value before adding x
  */
 extern (C) int atomicAdd32(int* val, int x) {
   asm {
     naked;
     enter 0,0;
     mov    EAX,x;
     mov    EBX,val;
     lock;
     xadd [EBX],EAX;
     leave;
     ret;
   }
 }

extern (C) int atomicAdd32(int* val, int x) { synchronized { *(cast(int*)val) += x; } }
 /** Atomically increment *val
  * \param val the value to increment
  */
 extern (C) void atomicInc32(int* val) {
   asm {
     naked;
     enter 0,0;
     mov    EBX,val;
     lock;
     inc [EBX];
     leave;
     ret;
   }
 }

extern (C) void atomicInc32(int* val) { return atomicAdd32(val, 1); }
 /** Atomically decrement *val
  * \param val the value to decrement
  */
 extern (C) void atomicDec32(int* val) {
   asm {
     naked;
     enter 0,0;
     mov    EBX,val;
     lock;
     dec [EBX];
     leave;
     ret;
   }
 }

extern (C) int atomicDec32(int* val, int x) { return atomicAdd32(val, -1); }
 /** Atomically set *val and return old value
  * \param val the value to set
  * \param newval the new value
  * \return the old value
  */
 extern (C) int atomicExchange32(int* val, int newval) {
   asm {
     naked;
     enter 0,0;
     mov    EAX,newval;
     mov    EBX,val;
     xchg [EBX],EAX;
     leave;
     ret;
   }
 }

extern (C) int atomicExchange32(int* val, int newval) { synchronized { int tmp = *cast(int*)val; *cast(int*)val = newval; return tmp; } }
Jan 26 2006
next sibling parent Carlos Santander <csantander619 gmail.com> writes:
Sean Kelly escribiˇ:
 Carlos Santander wrote:
 The following functions are part of Ben Hinkle's Locks library. I'm 
 using GDC on Mac (PPC), so assembler (especially x86 assembler) isn't 
 supported. I don't know assembly. Can somebody help me to translate 
 them to D, please?

Unfortunately, there is no perfect D equivalent. The purpose of these functions is twofold: first, there is typically a desire to impose access ordering to maintain algorithm correctness without using Mutexes, and second, to ensure that the data updates occur atomically (again, without Mutexes). Wrapping things in a 'synchronized' block should typically address the ordering issue (though it is not guaranteed as far as relevant specs on Mutexes are concerned--this is merely a common side-effect of how many Mutex implementations work), however, it can not cause the update to occur atomically. If you absolutely must use the Locks library, take my suggested code below and complement it by also only ever reading the variables pointed to by vptr while in a synchronized block. ie.

Kris escribiˇ:
 I thought the Mac was on x86 these days :-D

 Seriously though, Ben's port of Prof Lea's library uses the
 compareAndSet32() function only. Unless you have a specific (other) need,
 you can make life easier by dropping all the others.

 That aside, you can convert these to D for a single processor/single core
 CPU only. Anything else requires the equivalent of a bus-lock (with that
 'lock' prefix in the assembler), which D does not support at a higher level.
 From what I recall, Ben actually had non-assembler version of these
 functions ~ ones that would work only on a single-core machine:

Thank you, guys! -- Carlos Santander Bernal
Jan 26 2006
prev sibling parent reply Sean Kelly <sean f4.ca> writes:
Sean Kelly wrote:
 Carlos Santander wrote:
 The following functions are part of Ben Hinkle's Locks library. I'm 
 using GDC on Mac (PPC), so assembler (especially x86 assembler) isn't 
 supported. I don't know assembly. Can somebody help me to translate 
 them to D, please?

Unfortunately, there is no perfect D equivalent. The purpose of these functions is twofold: first, there is typically a desire to impose access ordering to maintain algorithm correctness without using Mutexes, and second, to ensure that the data updates occur atomically (again, without Mutexes).

I didn't explain the rest of this very well (yesterday was a long day), but the above outlines the basic idea. Essentially, compareAndSet and similar operations exploit low-level hardware functionality to perform certain simple operations that typically require mutual exclusion (ie. a mutex). The motivating factor is usually either to increase performance for very simple operations, to eliminate a mutual exclusion bottleneck, or to write algorithms that have some sort of progress guarantee. Since D doesn't support inline ASM for anything other than x86 at the moment, a PPC implementation would need to be written and compiled on GCC and accessed via extern (C) functions. It's probably easier to just forego the performance benefits of compareAndX and simply perform all read and write operations on the involved variables using a mutex. Or better yet to use a standard locking container unless you have a real need for a lock-free one. That said, I may still try to get PPC support working for std.atomic in Ares, with the caveat that it would basically be a front-end for a small C library. Sean
Jan 27 2006
parent reply James Dunne <james.jdunne gmail.com> writes:
Sean Kelly wrote:
 Sean Kelly wrote:
 
 Carlos Santander wrote:

 The following functions are part of Ben Hinkle's Locks library. I'm 
 using GDC on Mac (PPC), so assembler (especially x86 assembler) isn't 
 supported. I don't know assembly. Can somebody help me to translate 
 them to D, please?

Unfortunately, there is no perfect D equivalent. The purpose of these functions is twofold: first, there is typically a desire to impose access ordering to maintain algorithm correctness without using Mutexes, and second, to ensure that the data updates occur atomically (again, without Mutexes).

I didn't explain the rest of this very well (yesterday was a long day), but the above outlines the basic idea. Essentially, compareAndSet and similar operations exploit low-level hardware functionality to perform certain simple operations that typically require mutual exclusion (ie. a mutex). The motivating factor is usually either to increase performance for very simple operations, to eliminate a mutual exclusion bottleneck, or to write algorithms that have some sort of progress guarantee. Since D doesn't support inline ASM for anything other than x86 at the moment, a PPC implementation would need to be written and compiled on GCC and accessed via extern (C) functions. It's probably easier to just forego the performance benefits of compareAndX and simply perform all read and write operations on the involved variables using a mutex. Or better yet to use a standard locking container unless you have a real need for a lock-free one. That said, I may still try to get PPC support working for std.atomic in Ares, with the caveat that it would basically be a front-end for a small C library. Sean

In-language support for arbitrary assembly language would be key here, rather than x86(+) specific. This is a tough nut to crack though. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/MU/S d-pu s:+ a-->? C++++$ UL+++ P--- L+++ !E W-- N++ o? K? w--- O M-- V? PS PE Y+ PGP- t+ 5 X+ !R tv-->!tv b- DI++(+) D++ G e++>e h>--->++ r+++ y+++ ------END GEEK CODE BLOCK------ James Dunne
Jan 27 2006
parent reply Sean Kelly <sean f4.ca> writes:
James Dunne wrote:
 
 In-language support for arbitrary assembly language would be key here, 
 rather than x86(+) specific.  This is a tough nut to crack though.

Walter seems to want it. In fact he's argued in support of it in the C++ usenet forums. And based on what's been done for x86 ASM, it seems the intent is to support a syntax that's about as close to what's outlined in the appropriate hardware spec as possible. Ultimately, the D spec will probably include a statement to this effect (if there isn't one there already), and will leave the syntax and list of supported instructions to appendices. This is basically what Walter had suggested for C++ as well. Sean
Jan 27 2006
parent reply pragma <pragma_member pathlink.com> writes:
In article <drdr6v$25ka$1 digitaldaemon.com>, Sean Kelly says...
James Dunne wrote:
 
 In-language support for arbitrary assembly language would be key here, 
 rather than x86(+) specific.  This is a tough nut to crack though.

Walter seems to want it. In fact he's argued in support of it in the C++ usenet forums. And based on what's been done for x86 ASM, it seems the intent is to support a syntax that's about as close to what's outlined in the appropriate hardware spec as possible. Ultimately, the D spec will probably include a statement to this effect (if there isn't one there already), and will leave the syntax and list of supported instructions to appendices. This is basically what Walter had suggested for C++ as well.

(late to the party) Agreed. The asm{} statement should contain code that is platform specific (x86, PPC, ARM, 68K, 6502, z80, whatever), which is in turn version()'ed around as needed. I read the statement "arbitrary assembly language" and my mind zeroed in on the "arbitrary" port of that for a moment. For no explicable reason, I thought that perhaps the problem might be partially solved by a truely arbitrary asm syntax. Then I remembered: D already has some very elementary intrinsic functions in place. Shouldn't these be extended to cover the kind of operations that lockless primitives are based on (like Ares' atomic)? - EricAnderton at yahoo
Jan 27 2006
next sibling parent James Dunne <james.jdunne gmail.com> writes:
pragma wrote:
 In article <drdr6v$25ka$1 digitaldaemon.com>, Sean Kelly says...
 
James Dunne wrote:

In-language support for arbitrary assembly language would be key here, 
rather than x86(+) specific.  This is a tough nut to crack though.

Walter seems to want it. In fact he's argued in support of it in the C++ usenet forums. And based on what's been done for x86 ASM, it seems the intent is to support a syntax that's about as close to what's outlined in the appropriate hardware spec as possible. Ultimately, the D spec will probably include a statement to this effect (if there isn't one there already), and will leave the syntax and list of supported instructions to appendices. This is basically what Walter had suggested for C++ as well.

(late to the party) Agreed. The asm{} statement should contain code that is platform specific (x86, PPC, ARM, 68K, 6502, z80, whatever), which is in turn version()'ed around as needed. I read the statement "arbitrary assembly language" and my mind zeroed in on the "arbitrary" port of that for a moment. For no explicable reason, I thought that perhaps the problem might be partially solved by a truely arbitrary asm syntax. Then I remembered: D already has some very elementary intrinsic functions in place. Shouldn't these be extended to cover the kind of operations that lockless primitives are based on (like Ares' atomic)? - EricAnderton at yahoo

Yes, in the general case. But not when discussing vectorization and usage of SIMD extensions. ;) Moving into 64-bit land would be key here as well. -- Regards, James Dunne
Jan 27 2006
prev sibling parent reply Sean Kelly <sean f4.ca> writes:
pragma wrote:
 
 I read the statement "arbitrary assembly language" and my mind zeroed in on the
 "arbitrary" port of that for a moment.  For no explicable reason, I thought
that
 perhaps the problem might be partially solved by a truely arbitrary asm syntax.
 Then I remembered: D already has some very elementary intrinsic functions in
 place.  Shouldn't these be extended to cover the kind of operations that
 lockless primitives are based on (like Ares' atomic)?

It would probably not be too hard to provide intrinsic support for a CAS operation (with the caveat that it may compile to ~10 instructions on some architectures), but I don't see this offering much compared to a library API--std.atomic has support for unidirectional memory barriers and such, for example. That said, I think D could well benefit from memory access semantics that have more comprehensive support for concurrent operations, but this is a very nontrivial task. I think it would be better just to wait for the C++ folks to sort it out and hope they come up with something reasonable. Sean
Jan 29 2006
parent reply "Kris" <fu bar.com> writes:
Well, I guess the benefit is that a compiler-writer is already targeting a 
specific instruction-set, and thus could happily implement the appropriate 
intrinsic? A portable CAS intrinsic would permit one to write an 'atomic' 
library compatible with all platforms that D supports (and others in the 
future)?


"Sean Kelly" <sean f4.ca> wrote in message 
news:drj6km$brs$1 digitaldaemon.com...
 pragma wrote:
 I read the statement "arbitrary assembly language" and my mind zeroed in 
 on the
 "arbitrary" port of that for a moment.  For no explicable reason, I 
 thought that
 perhaps the problem might be partially solved by a truely arbitrary asm 
 syntax.
 Then I remembered: D already has some very elementary intrinsic functions 
 in
 place.  Shouldn't these be extended to cover the kind of operations that
 lockless primitives are based on (like Ares' atomic)?

It would probably not be too hard to provide intrinsic support for a CAS operation (with the caveat that it may compile to ~10 instructions on some architectures), but I don't see this offering much compared to a library API--std.atomic has support for unidirectional memory barriers and such, for example. That said, I think D could well benefit from memory access semantics that have more comprehensive support for concurrent operations, but this is a very nontrivial task. I think it would be better just to wait for the C++ folks to sort it out and hope they come up with something reasonable. Sean

Jan 29 2006
parent Sean Kelly <sean f4.ca> writes:
In the general case, yes.  But what about the unidirectional memory 
barrier issue?  And what about ordering loads (since this is required on 
some weaker memory models)?  I suppose you could redo my std.atomic as a 
set of intrinsics, but I don't see much to be gained from that over 
simply having it as a standard library component.  Just duplicating CAS 
as-is would be another option, but that all by itself is a bit more 
coarse-grained than people want in some situations.

Kris wrote:
 Well, I guess the benefit is that a compiler-writer is already targeting a 
 specific instruction-set, and thus could happily implement the appropriate 
 intrinsic? A portable CAS intrinsic would permit one to write an 'atomic' 
 library compatible with all platforms that D supports (and others in the 
 future)?
 
 
 "Sean Kelly" <sean f4.ca> wrote in message 
 news:drj6km$brs$1 digitaldaemon.com...
 pragma wrote:
 I read the statement "arbitrary assembly language" and my mind zeroed in 
 on the
 "arbitrary" port of that for a moment.  For no explicable reason, I 
 thought that
 perhaps the problem might be partially solved by a truely arbitrary asm 
 syntax.
 Then I remembered: D already has some very elementary intrinsic functions 
 in
 place.  Shouldn't these be extended to cover the kind of operations that
 lockless primitives are based on (like Ares' atomic)?

operation (with the caveat that it may compile to ~10 instructions on some architectures), but I don't see this offering much compared to a library API--std.atomic has support for unidirectional memory barriers and such, for example. That said, I think D could well benefit from memory access semantics that have more comprehensive support for concurrent operations, but this is a very nontrivial task. I think it would be better just to wait for the C++ folks to sort it out and hope they come up with something reasonable. Sean


Jan 29 2006
prev sibling parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Carlos Santander wrote:

 The following functions are part of Ben Hinkle's Locks library. I'm 
 using GDC on Mac (PPC), so assembler (especially x86 assembler) isn't 
 supported. I don't know assembly. Can somebody help me to translate them 
 to D, please?

I used the Mac OS X kernel functions instead of custom assembly, but weren't able to find all the functions it needed (e.g. 64-bit) Guess you could get away with just assert(false) on those now ? Take a look in Kernel.framework and libkern, under "OSAtomic": http://developer.apple.com/documentation/Darwin/Reference/ KernellibkernFramework/OSAtomic/index.html If you want to roll your own, Linux/NetBSD PPC should have asm... e.g. http://cvsweb.netbsd.org/bsdweb.cgi/src/ For the moment you'll have to do that in a separate C file though, since GDC does not (yet) support inline PowerPC assembler blocks. --anders
Jan 27 2006
next sibling parent Sean Kelly <sean f4.ca> writes:
Anders F Bj÷rklund wrote:
 Carlos Santander wrote:
 
 The following functions are part of Ben Hinkle's Locks library. I'm 
 using GDC on Mac (PPC), so assembler (especially x86 assembler) isn't 
 supported. I don't know assembly. Can somebody help me to translate 
 them to D, please?

I used the Mac OS X kernel functions instead of custom assembly, but weren't able to find all the functions it needed (e.g. 64-bit) Guess you could get away with just assert(false) on those now ?

Not all 32-bit hardware offers a 64-bit CAS instruction--x86 is one of the few. But this operation should not be necessary for most lock-free containers: slists, etc. If the Max offers kernel functions to perform these operations then it would be best to simply use those, and forget about anything that requires compareAndSet64. Sean
Jan 27 2006
prev sibling parent "Kris" <fu bar.com> writes:
Actually, only the compareAndSet32() is relevant. All those others are not 
used by the Locks package.


"Anders F Bj÷rklund" <afb algonet.se> wrote in message 
news:drcm94$k77$1 digitaldaemon.com...
 Carlos Santander wrote:

 The following functions are part of Ben Hinkle's Locks library. I'm using 
 GDC on Mac (PPC), so assembler (especially x86 assembler) isn't 
 supported. I don't know assembly. Can somebody help me to translate them 
 to D, please?

I used the Mac OS X kernel functions instead of custom assembly, but weren't able to find all the functions it needed (e.g. 64-bit) Guess you could get away with just assert(false) on those now ? Take a look in Kernel.framework and libkern, under "OSAtomic": http://developer.apple.com/documentation/Darwin/Reference/ KernellibkernFramework/OSAtomic/index.html If you want to roll your own, Linux/NetBSD PPC should have asm... e.g. http://cvsweb.netbsd.org/bsdweb.cgi/src/ For the moment you'll have to do that in a separate C file though, since GDC does not (yet) support inline PowerPC assembler blocks. --anders

Jan 27 2006