3

In a larger piece of code, I noticed that the g_atomic_* functions in glib were not doing what I expected, so I wrote this simple example:

#include <stdlib.h>
#include "glib.h"
#include "pthread.h"
#include "stdio.h"

void *set_foo(void *ptr) {
  g_atomic_int_set(((int*)ptr), 42);
  return NULL;
}

int main(void) {
  int foo = 0;
  pthread_t other;

  if (pthread_create(&other, NULL, set_foo, &foo)== 0) {
    pthread_join(other, NULL);
    printf("Got %d\n", g_atomic_int_get(&foo));
  } else {
    printf("Thread did not run\n");
    exit(1);
  }
}

When I compile this with GCC's '-E' option (stop after pre-processing), I notice that the call to g_atomic_int_get(&foo) has become:

(*(&foo))

and g_atomic_int_set(((int*)ptr), 42) has become:

((void) (*(((int*)ptr)) = (42)))

Clearly I was expecting some atomic compare and swap operations, not just simple (thread-unsafe) assignments. What am I doing wrong?

For reference my compile command looks like this:

gcc -m64 -E -o foo.E `pkg-config --cflags glib-2.0` -O0 -g foo.c
laslowh
  • 8,482
  • 5
  • 34
  • 45

1 Answers1

2

The architecture you are on does not require a memory barrier for atomic integer set/get operations, so the transformation is valid.

Here's where it's defined: http://git.gnome.org/browse/glib/tree/glib/gatomic.h#n60

This is a good thing, because otherwise you'd need to lock a global mutex for every atomic operation.

rmmh
  • 6,997
  • 26
  • 37
  • 1
    Interesting do you have any documentation of the fact that a memory barrier is not needed (uname -a gives "Linux rhel-5.4-dev 2.6.18-164.15.1.el5xen #1 SMP Mon Mar 1 11:11:42 EST 2010 x86_64 x86_64 x86_64 GNU/Linux" on my system). I wasn't aware that there were any architectures for which this is true, so I'd love to do some more reading about it. – laslowh Apr 09 '11 at 21:24