diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/bits.c | 68 | ||||
-rw-r--r-- | src/common/bits.h | 9 |
2 files changed, 77 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. * * * diff --git a/src/common/bits.h b/src/common/bits.h index 0e8ef65..074aac4 100644 --- a/src/common/bits.h +++ b/src/common/bits.h @@ -60,6 +60,9 @@ void set_all_in_bit_field(bitfield_t *); /* Bascule à 1 une partie d'un champ de bits. */ void set_in_bit_field(bitfield_t *, size_t, size_t); +/* Bascule à 1 de façon atomique une partie d'un champ de bits. */ +bool set_atomic_in_bit_field(bitfield_t *, size_t, size_t); + /* Réalise une opération ET logique entre deux champs de bits. */ void and_bit_field(bitfield_t *, const bitfield_t *); @@ -74,6 +77,7 @@ bool is_bit_field_equal_to(const bitfield_t *, const bitfield_t *); + unsigned long gfw(const bitfield_t *); @@ -104,4 +108,9 @@ bool test_in_mem_field(memfield_t *, const vmpa2t *); +#define set_atomic_in_mem_field(f, range) false + + + + #endif /* _COMMON_BITS_H */ |