From 65a4b8d9c1929fb7b171d630d336519fc4d418ef Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 24 Sep 2016 22:33:05 +0200
Subject: Replaced the non-working GLib atomic function to deal with bitfields.

---
 ChangeLog         |  5 +++++
 src/common/bits.c | 38 +++++++++++++++++++++++++++++---------
 2 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5c8b68e..6e8a942 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+16-09-24  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/common/bits.c:
+	Replace the non-working GLib atomic function to deal with bitfields.
+
 16-09-23  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/disass/output.c:
diff --git a/src/common/bits.c b/src/common/bits.c
index 42493f2..2aa1be5 100644
--- a/src/common/bits.c
+++ b/src/common/bits.c
@@ -356,31 +356,51 @@ bool set_atomic_in_bit_field(bitfield_t *field, size_t first, size_t count)
     size_t start;                           /* Mot de départ               */
     size_t end;                             /* Mot d'arrivée               */
     size_t remaining;                       /* Nombre de bits restants     */
-    unsigned long oldval;                   /* Ancienne valeur présente    */
     unsigned long mask;                     /* Nouvelle valeur à insérer   */
+    unsigned long oldval;                   /* Ancienne valeur présente    */
 
     start = first / (sizeof(unsigned long) * 8);
     end = (first + count - 1) / (sizeof(unsigned long) * 8);
 
-#if 0 //sizeof(gsize) != sizeof(unsigned long)
-#   warning "Can not perform atomic operations on bit fields!"
-#else
     if (start == end)
     {
         remaining = first % (sizeof(unsigned long) * 8);
 
-        assert(count > 0);
+        assert(count > 0 && count <= (sizeof(unsigned long) * 8));
 
-        mask = (1 << count) - 1;
-        mask <<= remaining;
+        if (count == 64)
+        {
+            assert(remaining == 0);
+            mask = ~0lu;
+        }
+        else
+        {
+            mask = (1lu << count) - 1;
+            mask <<= remaining;
+        }
 
-        oldval = g_atomic_pointer_or(&field->bits[start], mask);
+        /**
+         * Pour une raison inconnue, l'appel suivant est parfois sans effet :
+         *
+         *    oldval = g_atomic_pointer_or(&field->bits[start], mask);
+         *
+         * On bascule donc dans l'équivalent plus long à exécuter...
+         */
+
+        g_mutex_lock(&field->mutex);
+
+        oldval = field->bits[start];
+
+        field->bits[start] |= mask;
+
+        g_mutex_unlock(&field->mutex);
 
         result = ((oldval & mask) == 0);
 
+        assert(test_in_bit_field(field, first, count));
+
     }
     else
-#endif
     {
         g_mutex_lock(&field->mutex);
 
-- 
cgit v0.11.2-87-g4458