pass a structure to gcc built-ins for atomic accesses

284 Views Asked by At

I have a two structures just like below:

template <class T>
struct pointer_t
{
    T *ptr;
    uintptr_t tag;
};


template <class T>
struct Node
{
    T data;
    pointer_t<Node<T> > next;
};

and now I want to pass for example pointer_t<Node<T> > newNext to __sync_bool_compare_and_swap() function. According to the prototype of the function I pass:

__sync_bool_compare_and_swap((unsigned long*) &newTail.ptr->next, oldNext, newNext)

The problem is that if I don't cast newNext to unsigned long I'll get:

error: ‘struct pointer_t<Node<int> >’ used where a ‘long unsigned int’ was expected
      if ( __sync_bool_compare_and_swap((unsigned long*) &newTail.ptr->next, newNext, newNext) )

if I cast it to unsigned long then:

if ( __sync_bool_compare_and_swap((unsigned long*) &newTail.ptr->next, (unsigned long) oldNext, (unsigned long) newNext) )

I'll get:

error: ‘struct pointer_t<Node<int> >’ used where a ‘long unsigned int’ was expected.

can someone explain me you can I use __sync_bool_compare_and_swap with these two structures?

thanks

2

There are 2 best solutions below

1
On BEST ANSWER
#include <iostream>
#include <bitset>
using namespace std;

template <class T>
struct pointer_t
{
    T *ptr;
    uintptr_t tag;
};


template <class T>
struct Node
{
    T data;
    pointer_t<Node<T> >* next;
};

int main()
{
    Node<int> *newTail = new Node<int>();
    pointer_t<Node<int> > *oldNext = newTail->next;


    Node<int> *newNext = new Node<int>();

    pointer_t<Node<int> >* newNextPtr = new pointer_t<Node<int> >();
    newNextPtr->ptr=newNext;

    if ( __sync_bool_compare_and_swap(&newTail->next, oldNext, newNextPtr)) {
        std::cout<<"Gotcha!\n";
      }
 }

Which doesn't really solve your pointer tagging problem. If you want to achieve pointer tagging then, just steal a few unused bits from the pointer and set those bits to tag the pointer, then unset them to reset the pointer. Don't forget to untag the bits before dereferencing.

#define get_markedness(p) (((ptr_int) (p)) & 3)
#define get_unmarked_reference(p) ((void *) (((ptr_int) (p)) & (~3)))
#define get_marked_reference(p,m) ((void *) (((ptr_int) (p)) | m))
0
On