diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2017-01-27 23:22:49 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2017-01-27 23:22:49 (GMT) |
commit | 2b8f655628652f3cfb61c8b82d4b54fbf3ed9869 (patch) | |
tree | ecc32e82287a3402542c6bb204618a523e775889 /src/arch/instruction.c | |
parent | 36a006b2ac60c0cc1a2e2bea00d88508294be7f0 (diff) |
Avoided deadlocks in access to instruction sources and destinations.
Diffstat (limited to 'src/arch/instruction.c')
-rw-r--r-- | src/arch/instruction.c | 171 |
1 files changed, 127 insertions, 44 deletions
diff --git a/src/arch/instruction.c b/src/arch/instruction.c index db37bf7..f539ddb 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -51,6 +51,29 @@ static void g_arch_instruction_finalize(GArchInstruction *); +/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */ + + +/* Dénombre les liens présents à une extrémité donnée. */ +static size_t g_arch_instruction_get_link_counter(GArchInstruction *, bool); + +#define g_arch_instruction_get_source_counter(ins) \ + g_arch_instruction_get_link_counter(ins, true) + +#define g_arch_instruction_get_destination_counter(ins) \ + g_arch_instruction_get_link_counter(ins, false) + +/* Incrémente le nombre de liens définis à une extrémité donnée. */ +static size_t g_arch_instruction_inc_link_counter(GArchInstruction *, bool); + +#define g_arch_instruction_inc_source_counter(ins) \ + g_arch_instruction_inc_link_counter(ins, true) + +#define g_arch_instruction_inc_destination_counter(ins) \ + g_arch_instruction_inc_link_counter(ins, false) + + + /* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ @@ -124,10 +147,8 @@ static void g_arch_instruction_init(GArchInstruction *instr) { instr->max_displayed_len = VMPA_NO_PHYSICAL; - g_rw_lock_init(&instr->link_access); -#ifndef NDEBUG - g_atomic_int_set(&instr->hold_link_access, 0); -#endif + instr->from_count = 0; + instr->to_count = 0; } @@ -188,8 +209,6 @@ static void g_arch_instruction_dispose(GArchInstruction *instr) static void g_arch_instruction_finalize(GArchInstruction *instr) { - g_rw_lock_clear(&instr->link_access); - G_OBJECT_CLASS(g_arch_instruction_parent_class)->finalize(G_OBJECT(instr)); } @@ -548,6 +567,7 @@ void g_arch_instruction_get_rw_registers(const GArchInstruction *instr, GArchReg /****************************************************************************** * * * Paramètres : instr = instruction à mettre à jour. * +* src = sélection de l'extrémité à traiter. * * write = précise le type d'accès prévu (lecture/écriture). * * lock = indique le sens du verrouillage à mener. * * * @@ -559,28 +579,80 @@ void g_arch_instruction_get_rw_registers(const GArchInstruction *instr, GArchReg * * ******************************************************************************/ -void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool write, bool lock) +void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool src, bool write, bool lock) { -#ifndef NDEBUG - if (!lock) - g_atomic_int_dec_and_test(&instr->hold_link_access); -#endif + volatile gint *address; /* Choix de l'entier à traiter */ - if (write) - { - if (lock) g_rw_lock_writer_lock(&instr->link_access); - else g_rw_lock_writer_unlock(&instr->link_access); - } - else - { - if (lock) g_rw_lock_reader_lock(&instr->link_access); - else g_rw_lock_reader_unlock(&instr->link_access); - } + address = (src ? &instr->from_count : &instr->to_count); -#ifndef NDEBUG if (lock) - g_atomic_int_inc(&instr->hold_link_access); -#endif + g_bit_lock(address, INSTR_LINK_LOCK_BIT); + else + g_bit_unlock(address, INSTR_LINK_LOCK_BIT); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction dont les informations sont à consulter. * +* src = sélection de l'extrémité à traiter. * +* * +* Description : Dénombre les liens présents à une extrémité donnée. * +* * +* Retour : Quantité positive. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_arch_instruction_get_link_counter(GArchInstruction *instr, bool src) +{ + size_t result; /* Nombre de liens à renvoyer */ + volatile gint *address; /* Choix de l'entier à traiter */ + + address = (src ? &instr->from_count : &instr->to_count); + + assert(!g_bit_trylock(address, INSTR_LINK_LOCK_BIT)); + + result = g_atomic_int_get(address) & ~(1 << INSTR_LINK_LOCK_BIT); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction dont les informations sont à consulter. * +* src = sélection de l'extrémité à traiter. * +* * +* Description : Incrémente le nombre de liens définis à une extrémité donnée.* +* * +* Retour : Nouvelle quantité mise à jour. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_arch_instruction_inc_link_counter(GArchInstruction *instr, bool src) +{ + size_t result; /* Nombre de liens à renvoyer */ + volatile gint *address; /* Choix de l'entier à traiter */ + + address = (src ? &instr->from_count : &instr->to_count); + + assert(!g_bit_trylock(address, INSTR_LINK_LOCK_BIT)); + + result = g_atomic_int_get(address) & ~(1 << INSTR_LINK_LOCK_BIT); + + result++; + + assert((result & (1 << INSTR_LINK_LOCK_BIT)) == 0); + + g_atomic_int_set(address, (1 << INSTR_LINK_LOCK_BIT) | result); + + return result; } @@ -609,7 +681,7 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des g_arch_instruction_wlock_src(dest); - count = ++dest->from_count; + count = g_arch_instruction_inc_source_counter(dest); dest->from = (instr_link_t *)realloc(dest->from, count * sizeof(instr_link_t)); @@ -624,7 +696,7 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des g_arch_instruction_wlock_dest(instr); - count = ++instr->to_count; + count = g_arch_instruction_inc_destination_counter(instr); instr->to = (instr_link_t *)realloc(instr->to, count * sizeof(instr_link_t)); @@ -663,13 +735,13 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d result = false; - assert(g_atomic_int_get(&instr->hold_link_access) > 0); + assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT)); g_arch_instruction_wlock_src(dest); /* Côté destination */ - count = dest->from_count; + count = g_arch_instruction_get_source_counter(dest); for (i = 0; i < count; i++) if (dest->from[i].linked == instr && dest->from[i].type == old) @@ -682,7 +754,7 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d /* Côté point de départ */ - count = instr->to_count; + count = g_arch_instruction_get_destination_counter(instr); for (i = 0; i < count; i++) if (instr->to[i].linked == dest && instr->to[i].type == old) @@ -722,11 +794,15 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d * * ******************************************************************************/ -bool g_arch_instruction_has_sources(const GArchInstruction *instr) +bool g_arch_instruction_has_sources(GArchInstruction *instr) { - assert(g_atomic_int_get(&instr->hold_link_access) > 0); + size_t count; /* Nombre de liens présents */ + + assert(!g_bit_trylock(&instr->from_count, INSTR_LINK_LOCK_BIT)); - return (instr->from_count > 0); + count = g_arch_instruction_get_source_counter(instr); + + return (count > 0); } @@ -744,14 +820,14 @@ bool g_arch_instruction_has_sources(const GArchInstruction *instr) * * ******************************************************************************/ -size_t g_arch_instruction_get_sources(const GArchInstruction *instr, instr_link_t **sources) +size_t g_arch_instruction_get_sources(GArchInstruction *instr, instr_link_t **sources) { - assert(g_atomic_int_get(&instr->hold_link_access) > 0); + assert(!g_bit_trylock(&instr->from_count, INSTR_LINK_LOCK_BIT)); if (sources != NULL) *sources = instr->from; - return instr->from_count; + return g_arch_instruction_get_source_counter(instr); } @@ -768,11 +844,15 @@ size_t g_arch_instruction_get_sources(const GArchInstruction *instr, instr_link_ * * ******************************************************************************/ -bool g_arch_instruction_has_destinations(const GArchInstruction *instr) +bool g_arch_instruction_has_destinations(GArchInstruction *instr) { - assert(g_atomic_int_get(&instr->hold_link_access) > 0); + size_t count; /* Nombre de liens présents */ + + assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT)); - return (instr->to_count > 0); + count = g_arch_instruction_get_destination_counter(instr); + + return (count > 0); } @@ -790,14 +870,14 @@ bool g_arch_instruction_has_destinations(const GArchInstruction *instr) * * ******************************************************************************/ -size_t g_arch_instruction_get_destinations(const GArchInstruction *instr, instr_link_t **dests) +size_t g_arch_instruction_get_destinations(GArchInstruction *instr, instr_link_t **dests) { - assert(g_atomic_int_get(&instr->hold_link_access) > 0); + assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT)); if (dests != NULL) *dests = instr->to; - return instr->to_count; + return g_arch_instruction_get_destination_counter(instr); } @@ -815,16 +895,19 @@ size_t g_arch_instruction_get_destinations(const GArchInstruction *instr, instr_ * * ******************************************************************************/ -GArchInstruction *g_arch_instruction_get_given_destination(const GArchInstruction *instr, InstructionLinkType type) +GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *instr, InstructionLinkType type) { GArchInstruction *result; /* Résultat à remonter */ + size_t count; /* Nombre de liens à parcourir */ size_t i; /* Boucle de parcours */ result = NULL; - assert(g_atomic_int_get(&instr->hold_link_access) > 0); + assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT)); + + count = g_arch_instruction_get_destination_counter(instr); - for (i = 0; i < instr->to_count && result == NULL; i++) + for (i = 0; i < count && result == NULL; i++) if (instr->to[i].type == type) result = instr->to[i].linked; |