summaryrefslogtreecommitdiff
path: root/src/common/bits.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/bits.c')
-rw-r--r--src/common/bits.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/common/bits.c b/src/common/bits.c
index d451100..b08dcb4 100644
--- a/src/common/bits.c
+++ b/src/common/bits.c
@@ -25,6 +25,7 @@
#include <assert.h>
+#include <glib.h>
#include <malloc.h>
#include <string.h>
@@ -41,6 +42,7 @@ struct _bitfield_t
void *tail; /* Limite du tableau de bits */
+ GMutex mutex; /* Garantie d'atomicité */
unsigned long bits[0]; /* Mémoire d'accès associée */
};
@@ -94,6 +96,8 @@ static bitfield_t *_create_bit_field(size_t length, bool state, size_t extra)
result->tail = ((char *)result) + base;
+ g_mutex_init(&result->mutex);
+
if (state)
set_all_in_bit_field(result);
else
@@ -177,6 +181,8 @@ bitfield_t *create_bit_field_from(const bitfield_t *field)
void delete_bit_field(bitfield_t *field)
{
+ g_mutex_clear(&field->mutex);
+
free(field);
}
@@ -330,6 +336,68 @@ void set_in_bit_field(bitfield_t *field, size_t first, size_t count)
/******************************************************************************
* *
+* Paramètres : field = champ de bits à modifier. *
+* first = indice du premier bit à traiter. *
+* count = nombre de bits à marquer. *
+* *
+* Description : Bascule à 1 de façon atomique une partie d'un champ de bits. *
+* *
+* Retour : true si la zone traitée était entièrement vierge. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool set_atomic_in_bit_field(bitfield_t *field, size_t first, size_t count)
+{
+ bool result; /* Bilan à retourner */
+ 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 */
+
+ 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);
+
+ mask = (1 << count) - 1;
+ mask <<= remaining;
+
+ oldval = g_atomic_pointer_or(&field->bits[start], mask);
+
+ result = ((oldval & mask) == 0);
+
+ }
+ else
+#endif
+ {
+ g_mutex_lock(&field->mutex);
+
+ result = !test_in_bit_field(field, first, count);
+
+ if (result)
+ set_in_bit_field(field, first, count);
+
+ g_mutex_unlock(&field->mutex);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : dest = champ de bits à modifier. *
* src = champ de bits à utiliser pour l'opération. *
* *