After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 650823 - expand the set of atomic ops
expand the set of atomic ops
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: general
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on: 650935
Blocks:
 
 
Reported: 2011-05-22 21:42 UTC by Matthias Clasen
Modified: 2011-05-30 11:55 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
here is a patch (9.88 KB, patch)
2011-05-22 21:42 UTC, Matthias Clasen
none Details | Review
optimize bitlocks (1.89 KB, patch)
2011-05-22 21:52 UTC, Matthias Clasen
none Details | Review
Add pointer sized atomic ops (6.41 KB, patch)
2011-05-25 10:28 UTC, Alexander Larsson
none Details | Review
Implement pointer sized bitlocks (5.10 KB, patch)
2011-05-25 10:28 UTC, Alexander Larsson
none Details | Review

Description Matthias Clasen 2011-05-22 21:42:27 UTC
As has become apparent in bug 617491, it would be useful to have more 
exchange-and-bitop atomic operations available. gcc offers a variety of these as builtins, and we can easily provide generic versions that do 

atomic_get
bitop
atomic_exchange_and_set

in a loop.
Comment 1 Matthias Clasen 2011-05-22 21:42:46 UTC
Created attachment 188352 [details] [review]
here is a patch
Comment 2 Matthias Clasen 2011-05-22 21:52:00 UTC
Created attachment 188353 [details] [review]
optimize bitlocks
Comment 3 Allison Karlitskaya (desrt) 2011-05-23 04:56:24 UTC
I really don't like the _exchange_ in the name here since these operations don't exchange anything at all.

I think we're better off calling them one of:

  g_atomic_int_fetch_and_and
  g_atomic_int_get_and_and
  g_atomic_int_and

The last variant has the advantage of not seeing 'and_and' and 'and_or' in function names.

Note that the macro version of g_atomic_int_add is already:

#define g_atomic_int_add(atomic,val) \
  __sync_fetch_and_add((atomic),(val))

so g_atomic_int_add is already 'fetch and add' (at least sometimes...)
Comment 4 Allison Karlitskaya (desrt) 2011-05-23 04:57:17 UTC
implied: we would deprecate g_atomic_int_exchange_and_add
Comment 5 Matthias Clasen 2011-05-23 11:47:13 UTC
the short names would be ok for me

g_atomic_int_{add,sub,and,or,xor,nand}

I'm not super-keen on deprecating...
Comment 6 Alexander Larsson 2011-05-24 13:03:21 UTC
g_atomic_int_add already exists, returning void rather than the previous value.
Comment 7 Alexander Larsson 2011-05-24 13:18:02 UTC
g_atomic_int_exchange_and_and seems to be declared twice in the header.

Also:

gint  g_atomic_int_exchange_and_and (volatile gint G_GNUC_MAY_ALIAS *atomic,
                                     gint               val);

#define g_atomic_int_exchange_and_add(atomic,val) \
  __sync_fetch_and_add((atomic),(val))

I worry a bit about the types here. If you hit the function then your arguments will be auto-converted to the right integer size type. But if you hit the macro it will instead cause a different size be used for the atomic due to the macro magic in the gcc things. I think we should add some manual casts here.
Comment 8 Alexander Larsson 2011-05-24 13:22:57 UTC
Oh, no i misread and_add for one of the and_and:s :)
Comment 9 Alexander Larsson 2011-05-24 13:32:19 UTC
Also:

+gint
+gint
+g_atomic_int_exchange_and_nand (volatile gint G_GNUC_MAY_ALIAS *atomic,
Comment 10 Alexander Larsson 2011-05-24 13:37:05 UTC
gatomic-gcc.c: In function 'g_atomic_int_exchange_and_nand':
gatomic-gcc.c:166:32: note: '__sync_fetch_and_nand' changed semantics in GCC 4.4


Sounds scary. Do we really need nand?
Comment 11 Allison Karlitskaya (desrt) 2011-05-24 14:36:00 UTC
My initial impression was also that 'nand' would not be particularly helpful and that I wouldn't intuitively know how I expected it to work.  Seems that the GCC developers didn't know either...

We should resolve bug 650935 (one way or the other) before committing anything here.

(In reply to comment #7)
> I worry a bit about the types here. If you hit the function then your arguments
> will be auto-converted to the right integer size type. But if you hit the macro
> it will instead cause a different size be used for the atomic due to the macro
> magic in the gcc things. I think we should add some manual casts here.

This is not just a problem with the input types but also the return types.  In the pointer case the atomic operations are used on gsize* and people still expect gpointer to be returned (since they expect that it is a function).
Comment 12 Alexander Larsson 2011-05-25 10:28:27 UTC
Created attachment 188570 [details] [review]
Add pointer sized atomic ops

These are nice since they can be used for bitlocks and gdatalist flags.
Comment 13 Alexander Larsson 2011-05-25 10:28:38 UTC
Created attachment 188571 [details] [review]
Implement pointer sized bitlocks
Comment 14 Alexander Larsson 2011-05-25 10:54:03 UTC
pointer atomics and bitlocks needed for the optimizations in bug 650458
Comment 15 Alexander Larsson 2011-05-25 10:56:35 UTC
I should not that i'm slightly unsure about the details of accessing some memory atomically at different sizes. I.e. on 64bit arches all updates of the pointer bitlock are using atomic 64bit writes (and reads), but the read in the futex code is 32bit.

Does a 64bit atomic write guarantee atomicity of a 32bit atomic read of the same data?
Comment 16 Alexander Larsson 2011-05-25 12:21:08 UTC
Random atomic/bitlock question, how does the ARM spinlock protected atomic primitives work wrt the atomic read in the kernel in the futex syscall. The kernel can hardly be using the userspace spinlock...
Comment 17 Alexander Larsson 2011-05-25 12:25:15 UTC
In fact, some googling around makes me worry that ARM SMP futex support is not really all implemented yet, and we should handle ENOSYS from the futex calls at runtime...
Comment 18 Matthias Clasen 2011-05-25 14:21:48 UTC
I think making sense of all this (atomics, bitlocks, etc) on arm requires someone with interest in that platform and available hw to jump in...
Comment 19 Allison Karlitskaya (desrt) 2011-05-28 20:17:20 UTC
commit 83821352657a9481dbff6ab04e8ae60566c17d5e
Author: Ryan Lortie <desrt@desrt.ca>
Date:   Sat May 28 15:59:18 2011 -0400

    glib: Rewrite gatomic.[ch]
    
     - remove all inline assembly versions
    
     - implement the atomic operations using either GCC intrinsics, the
       Windows interlocked API or a mutex-based fallback
    
     - drop gatomic-gcc.c since these are now defined in the header file.
       Adjust Makefile.am accordingly.
    
     - expand the set of operations: support 'get', 'set', 'compare and
       exchange', 'add', 'or', and 'xor' for both integers and pointers
    
     - deprecate g_atomic_int_exchange_and_add since g_atomic_int_add (as
       with all the new arithmetic operations) now returns the prior value
    
     - unify the use of macros: all functions are now wrapped in macros that
       perform the proper casts and checks
    
     - remove G_GNUC_MAY_ALIAS use; it was never required for the integer
       operations (since casting between pointers that only vary in
       signedness of the target is explicitly permitted) and we avoid the
       need for the pointer operations by using simple 'void *' instead of
       'gpointer *' (which caused the 'type-punned pointer' warning)
    
     - provide function implementations of g_atomic_int_inc and
       g_atomic_int_dec_and_test: these were strictly macros before
    
     - improve the documentation to make it very clear exactly which types
       of pointers these operations may be used with
    
     - remove a few uses of the now-deprecated g_atomic_int_exchange_and_add
    
     - drop initialisation of gatomic from gthread (by using a GStaticMutex
       instead of a GMutex)
    
     - update glib.symbols and documentation sections files
    
    Closes #650823 and #650935
Comment 20 Matthias Clasen 2011-05-29 13:57:58 UTC
Review of attachment 188571 [details] [review]:

::: glib/gbitlock.c
@@ +350,3 @@
+    {
+      int_v = pointer_int_part (v, lock_bit);
+      int_address = address_of_int_part (address, lock_bit);

I wonder why we need two 'icky' functions here. Can't we figure out the address first, and then simply do

int_v = *int_address 

?

@@ +386,3 @@
+
+/**
+ * g_pointer_bit_tryunlock:

Obvious copy-paste accident here
Comment 21 Alexander Larsson 2011-05-30 11:53:13 UTC
Review of attachment 188571 [details] [review]:

::: glib/gbitlock.c
@@ +350,3 @@
+    {
+      int_v = pointer_int_part (v, lock_bit);
+      int_address = address_of_int_part (address, lock_bit);

Eh? But those are not the same. int_v is the old value returned from before the atomic or. *int_address is the new value that futex() checks to see if its the same as the passed in value (i.e. int_v).
Comment 22 Alexander Larsson 2011-05-30 11:55:00 UTC
I fixed up the copy-paste accident and moved this patch to bug 651467.