summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-09-24 20:33:05 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-09-24 20:33:05 (GMT)
commit65a4b8d9c1929fb7b171d630d336519fc4d418ef (patch)
tree1883080d3b92989d9c06f8d5085a54b7e6aad0b9
parente2bce994e554cb598ed9547ba5ecf22be748ddfd (diff)
Replaced the non-working GLib atomic function to deal with bitfields.
-rw-r--r--ChangeLog5
-rw-r--r--src/common/bits.c38
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);