diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/bits.c | 38 |
1 files changed, 29 insertions, 9 deletions
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); |