Page 1 of 1

64bit Interlocked*

Posted: Tue Oct 07, 2014 7:19 pm
by cas
I can not use any Interlocked* functions when trying to compile app for 64bit.

Use of any of the following 3 functions (that operate only on 32bit values) result in error:
POLINK: error: Unresolved external symbol 'InterlockedIncrement'.
POLINK: error: Unresolved external symbol 'InterlockedDecrement'.
POLINK: error: Unresolved external symbol 'InterlockedExchangeAdd'.
But that is not important, since i want to operate on 64bit values, i actually need these functions:

Code: Select all

InterlockedIncrement64
InterlockedDecrement64
InterlockedExchangeAdd64
Unfortunately, these 3 functions are intrinsic and not exported in any static or dynamic library.

Is it possible to use them directly in PureBasic (x64)?

Only option i can see right now is to create proxy static lib for these functions with some 64bit c++ compiler and import that lib in PureBasic.

Maybe this is a bug? Or maybe not and i need to make feature request for these 64bit functions to be included in future 64bit PureBasic versions?

Thanks

Re: 64bit Interlocked*

Posted: Tue Oct 07, 2014 8:01 pm
by ts-soft

Code: Select all

ImportC ""
  InterlockedIncrement64(*addend)
  InterlockedDecrement64(*addend)
  InterlockedExchangeAdd64(*addend, value.q)
EndImport

Re: 64bit Interlocked*

Posted: Tue Oct 07, 2014 8:34 pm
by cas
I tried that already and it does not work.

Look on MSDN, for example, InterlockedIncrement it says that it is exported in static (Kernel32.lib) and dynamic library (Kernel32.dll).

And now look for InterlockedIncrement64, it says:
This function is implemented using a compiler intrinsic where possible.
There is no lib or dll for this function if i understand this correctly.



Edit:

I checked c++ headers for these 3 functions and i see that these functions are implemented on top of InterlockedCompareExchange64.
Unfortunately, InterlockedCompareExchange64 is only exported in 32bit kernel32.dll and not in 64bit.

Now the only problem is how to make InterlockedCompareExchange64 to work in 64bit PureBasic? Then i could easily convert these 3 c++ functions to PB.

Thanks

Re: 64bit Interlocked*

Posted: Tue Oct 07, 2014 9:42 pm
by Josh
PBs Kernel32.lib doesn't include the functions Interlocked...64

Try to use OpenLibrary with GetFunction. Sorry, can't test at the moment, no x64 on board yet.

Re: 64bit Interlocked*

Posted: Tue Oct 07, 2014 10:17 pm
by cas
I already tried GetFunction() and that's why i wrote in my previous post that InterlockedCompareExchange64 is only exported in 32bit kernel32.dll.

And i just built 64bit static lib with these 3 functions exported. It works perfectly in PureBasic.
If anyone else need to use these functions with 64bit PureBasic, let me know and i will post it here.

Re: 64bit Interlocked*

Posted: Mon Oct 13, 2014 12:41 am
by RichAlgeni
I'd love to know what you use it for! Yes, please post!!!

Re: 64bit Interlocked*

Posted: Wed Oct 15, 2014 10:22 am
by doctorized
Could this help?

Code: Select all

CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
   ImportC ""
     InterlockedIncrement
     InterlockedDecrement
     InterlockedExchangeAdd
   EndImport
Else
   ImportC ""
      InterlockedIncrement64(*addend)
      InterlockedDecrement64(*addend)
      InterlockedExchangeAdd64(*addend, value.q)
   EndImport
EndCompilerIf

Re: 64bit Interlocked*

Posted: Wed Oct 15, 2014 10:29 am
by Fred
You should be able to get the Kernel32.lib from the official MS Windows SDK and it should work.

Re: 64bit Interlocked*

Posted: Sat Nov 08, 2014 1:03 pm
by Mistrel
As these functions map directly to assembly, you can add them yourself fairly easily with PureBasic's inline ASM.

Here are some examples for cross-platform atomic exchange/compare exchange for x86 and x64. The advantage of these functions over using Win32 is that you can take them with you if you decide to compile on a platform other than Windows:

http://www.purebasic.fr/english/viewtop ... 12&t=38024

Re: 64bit Interlocked*

Posted: Sat Aug 01, 2015 3:40 am
by RichAlgeni
I have downloaded the 8.1 development kit, it does not contain the code for InterlockedIncrement64.

It does however, for the slim reader writer lock.

If anyone has this working, I'd love to see it.

Re: 64bit Interlocked*

Posted: Wed Mar 14, 2018 11:49 pm
by RichAlgeni
Cas, could you post your library please???

Thanks!

Re: 64bit Interlocked*

Posted: Thu Mar 15, 2018 12:21 am
by cas
Thanks to Mistrel for his ASM code (xchg and cmpxchg) that he posted here: http://www.purebasic.fr/english/viewtop ... 12&t=38024
now i can drop lib and implement these interlocked functions in PureBasic.

interlocked.pbi:

Code: Select all

EnableExplicit

CompilerSelect #PB_Compiler_Processor
  CompilerCase #PB_Processor_x86
    Procedure InterlockedExchange(*Destination.Integer, Value.i)
      !mov ecx,[p.p_Destination]
      !mov eax,[p.v_Value]
      !xchg [ecx],eax
      ProcedureReturn
    EndProcedure
    Procedure InterlockedCompareExchange(*Destination.Integer, Exchange.i, Comparand.i)
      !mov ecx,[p.p_Destination]
      !mov eax,[p.v_Comparand]
      !mov edx,[p.v_Exchange]
      !lock cmpxchg [ecx],edx 
      ProcedureReturn
    EndProcedure
  CompilerCase #PB_Processor_x64
    Procedure InterlockedExchange(*Destination.Integer, Value.i)
      !mov rcx,[p.p_Destination]
      !mov rax,[p.v_Value]
      !xchg [rcx],rax
      ProcedureReturn
    EndProcedure
    Procedure InterlockedCompareExchange(*Destination.Integer, Exchange.i, Comparand.i)
      !mov rcx,[p.p_Destination]
      !mov rax,[p.v_Comparand]
      !mov rdx,[p.v_Exchange]
      !lock cmpxchg [rcx],rdx
      ProcedureReturn
    EndProcedure
CompilerEndSelect

Procedure InterlockedIncrement(*Addend.Integer)
  Protected Old.i
  Repeat
    Old.i = *Addend\i
  Until InterlockedCompareExchange(*Addend, Old + 1, Old) = Old
  ProcedureReturn Old + 1
EndProcedure

Procedure InterlockedDecrement(*Addend.Integer)
  Protected Old.i
  Repeat
    Old = *Addend\i
  Until InterlockedCompareExchange(*Addend, Old - 1, Old) = Old
  ProcedureReturn Old - 1
EndProcedure

Procedure InterlockedAdd(*Addend.Integer, Value.i)
  Protected Old.i
  Repeat
    Old = *Addend\i
  Until InterlockedCompareExchange(*Addend, Old + Value, Old) = Old
  ProcedureReturn Old + Value
EndProcedure

Procedure InterlockedExchangeAdd(*Addend.Integer,Value.i)
  Protected Old.i
  Repeat
    Old = *Addend\i
  Until InterlockedCompareExchange(*Addend, Old + Value, Old) = Old
  ProcedureReturn Old
EndProcedure

CompilerIf #PB_Compiler_IsMainFile And #PB_Compiler_Debugger ;test
  Define a=100
  Debug a
  Debug InterlockedDecrement(@a)
  Debug a
CompilerEndIf
Works great with both x86 and x64 PureBasic.

Re: 64bit Interlocked*

Posted: Thu Mar 15, 2018 12:47 am
by RichAlgeni
Thanks Cas!!!