Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I implement a portable pointer compare and swap?

Tags:

c

intrinsics

I have found this code for compareAndSwap in a StackOverflow answer:

boolean CompareAndSwapPointer(volatile * void * ptr,
                              void * new_value,
                              void * old_value) {
#if defined(_MSC_VER)
   if (InterlockedCompareExchange(ptr, new_value, old_value) == old_value) return false;
   else return true;
#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
   return __sync_bool_compare_and_swap(ptr, old_value, new_value);
#else
#  error No implementation
#endif
}

Is this the most proper way of having portable fast code, (Except assembly inlining).

Also, one problem is that those specific builtin methods have different parameters and return values from one compiler to another, which may require some additional changes like the if then else in this example.

Also another problem would be the behavior of these builtin methods in the machine code level, do they behave exactly the same ? (e.g use the same assembly instructions)

Note: Another problem would be if there is many supported platforms not just (Windows and Linux) as in this example. The code might get very big.

like image 473
Bionix1441 Avatar asked Jul 02 '15 10:07

Bionix1441


3 Answers

I would use a Hardware Abstraction Layer, (HAL) that allows generic code to be common - and any portable source can be included and build for each platform.

In my opinion, this allows for better structured and more readable source.

To allow you to better understand this process I would suggest Google for finding examples and explanations.

Hopefully this brief answer helps.

[EDIT] I will attempt a simple example for Bionix, to show how to implement a HAL system...

  • Mr A wants his application to run on his 'Tianhe-2' and also his 'Amiga 500'. He has the cross compilers etc and will build both binaries on his PC. He want to read keys and print to the screen.

mrAMainApplication.c contains the following...

#include "hal.h"

// This gets called every time around the main loop ...
void mainProcessLoop( void )
{
   unsigned char key = 0;

   // scan key ...
   key = hal_ReadKey();

   if ( key != 0 )
   {
       hal_PrintChar( key );
   }
}

He then creates a header file (Remember - this is an example, not working code! )... He creates hal.h ...

#ifndef _HAL_H_
#define _HAL_H_

unsigned char hal_ReadKey( void );
unsigned char hal_PrintChar( unsigned char pKey );

#endif // _HAL_H_

Now Mr A needs two separate source files, one for his 'Tianhe-2' system and another for his Amiga 500...

hal_A500.c

void hal_ReadKey( void )
{
    // Amiga related code for reading KEYBOARD
}

void hal_PrintChar( unsigned char pKey )
{
    // Amiga related code for printing to a shell...
}

hal_Tianhe2_VERYFAST.c

void hal_ReadKey( void )
{
    // Tianhe-2 related code for reading KEYBOARD
}

void hal_PrintChar( unsigned char pKey )
{
    // Tianhe-2 related code for printing to a shell...
}

Mr A then - when building for the Amiga - builds mrAmainApplication.c and hal_A500.c When building for the Tianhe-2 - he uses hal_Tianhe2_VERYFAST.c instead of hal_A500.c

Right - I've written this example with some humour, this is not ear-marked at anyone, just I feel it makes the example more interesting and hopefully aids in understanding.

Neil

like image 176
Neil Avatar answered Nov 01 '22 07:11

Neil


In modern C, starting with C11, use _Atomic for the type qualification and atomic_compare_exchange_weak for the function.

The newer versions of gcc and clang are compliant to C11 and implement these operations in a portable way.

like image 20
Jens Gustedt Avatar answered Nov 01 '22 07:11

Jens Gustedt


Take a look at ConcurrencyKit and possibly you can use higher level primitives which is probably what most of the time people really want. In contrast to HAL which somewhat OS specific, I believe CK works on Windows and with a number of non-gcc compilers.

But if you are just interested in how to implement "compare-and-swap" or atomic actions portably on a wide variety of C compilers, look and see how that code works. It is all open-source.

I suspect that the details can get messy and they are not something that in general will make for easy or interesting exposition here for the general public.

like image 1
rocky Avatar answered Nov 01 '22 08:11

rocky