64bit Interlocked*

Windows specific forum
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

64bit Interlocked*

Post 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
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: 64bit Interlocked*

Post by ts-soft »

Code: Select all

ImportC ""
  InterlockedIncrement64(*addend)
  InterlockedDecrement64(*addend)
  InterlockedExchangeAdd64(*addend, value.q)
EndImport
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

Re: 64bit Interlocked*

Post 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
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: 64bit Interlocked*

Post 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.
sorry for my bad english
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

Re: 64bit Interlocked*

Post 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.
User avatar
RichAlgeni
Addict
Addict
Posts: 914
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: 64bit Interlocked*

Post by RichAlgeni »

I'd love to know what you use it for! Yes, please post!!!
User avatar
doctorized
Addict
Addict
Posts: 854
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Re: 64bit Interlocked*

Post 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
Fred
Administrator
Administrator
Posts: 16621
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: 64bit Interlocked*

Post by Fred »

You should be able to get the Kernel32.lib from the official MS Windows SDK and it should work.
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Re: 64bit Interlocked*

Post 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
User avatar
RichAlgeni
Addict
Addict
Posts: 914
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: 64bit Interlocked*

Post 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.
User avatar
RichAlgeni
Addict
Addict
Posts: 914
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: 64bit Interlocked*

Post by RichAlgeni »

Cas, could you post your library please???

Thanks!
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

Re: 64bit Interlocked*

Post 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.
User avatar
RichAlgeni
Addict
Addict
Posts: 914
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: 64bit Interlocked*

Post by RichAlgeni »

Thanks Cas!!!
Post Reply