diff options
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/instruction-int.h | 11 | ||||
-rw-r--r-- | src/arch/instruction.c | 130 | ||||
-rw-r--r-- | src/arch/instruction.h | 18 |
3 files changed, 152 insertions, 7 deletions
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h index eca2807..69cdc8a 100644 --- a/src/arch/instruction-int.h +++ b/src/arch/instruction-int.h @@ -80,10 +80,19 @@ struct _GArchInstruction GArchInstruction **from; /* Origines des références */ InstructionLinkType *from_types; /* Type des liens de dest. */ size_t from_count; /* Nombre de ces origines */ + GRWLock from_access; /* Verrou de protection */ +#ifndef NDEBUG + gint hold_from_access; /* Suivi des verrouillages */ +#endif + GArchInstruction **to; /* Eventuelles lignes visées */ InstructionLinkType *to_types; /* Type des liens de dest. */ link_extra_info *links_info; /* Informations complémentaires*/ size_t to_count; /* Nombre de ces destinations */ + GRWLock to_access; /* Verrou de protection */ +#ifndef NDEBUG + gint hold_to_access; /* Suivi des verrouillages */ +#endif get_instruction_rw_regs_fc get_rw_regs; /* Liste des registres liés */ //print_instruction_fc print; /* Imprime l'ensemble */ @@ -91,7 +100,7 @@ struct _GArchInstruction //is_instruction_return_fc is_return; /* Retour de fonction ou pas ? */ decomp_instr_fc decomp; /* Procédure de décompilation */ - bool is_return; /* Retour de fonction ou pas ? */ + bool is_return; /* Retour de fonction ou pas ? */ // FIXME : à virer }; diff --git a/src/arch/instruction.c b/src/arch/instruction.c index 46f533e..4de70b7 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -107,6 +107,12 @@ static void g_arch_instruction_init(GArchInstruction *instr) instr->is_return = false; + g_rw_lock_init(&instr->from_access); + g_atomic_int_set(&instr->hold_from_access, 0); + + g_rw_lock_init(&instr->to_access); + g_atomic_int_set(&instr->hold_to_access, 0); + } @@ -143,6 +149,9 @@ static void g_arch_instruction_dispose(GArchInstruction *instr) static void g_arch_instruction_finalize(GArchInstruction *instr) { + g_rw_lock_clear(&instr->from_access); + g_rw_lock_clear(&instr->to_access); + G_OBJECT_CLASS(g_arch_instruction_parent_class)->finalize(G_OBJECT(instr)); } @@ -558,6 +567,8 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des /* Côté destination */ + g_arch_instruction_wlock_src(dest); + count = ++dest->from_count; dest->from = (GArchInstruction **)realloc(dest->from, @@ -568,8 +579,12 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des dest->from[count - 1] = instr; dest->from_types[count - 1] = type; + g_arch_instruction_wunlock_src(dest); + /* Côté point de départ */ + g_arch_instruction_wlock_dest(instr); + count = ++instr->to_count; instr->to = (GArchInstruction **)realloc(instr->to, @@ -595,6 +610,8 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des va_end(ap); + g_arch_instruction_wunlock_dest(instr); + } @@ -609,17 +626,24 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des * * * Retour : true pour une mise à jour réussie, false sinon. * * * -* Remarques : - * +* Remarques : Le verrou doit être posé sur les destination de 'instr'. * * * ******************************************************************************/ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType old, InstructionLinkType new) { + bool result; /* Bilan à retourner */ size_t count; /* Raccourci pour la lecture */ size_t i; /* Boucle de parcours */ size_t from_idx; /* Indice côté destination */ size_t to_idx; /* Indice côté source */ + result = false; + + assert(g_atomic_int_get(&instr->hold_to_access) > 0); + + g_arch_instruction_wlock_src(dest); + /* Côté destination */ count = dest->from_count; @@ -629,7 +653,7 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d break; if (i == count) - return false; + goto gaicl_exit; else from_idx = i; @@ -642,7 +666,7 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d break; if (i == count) - return false; + goto gaicl_exit; else to_idx = i; @@ -652,7 +676,13 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d instr->to_types[to_idx] = new; - return true; + result = true; + + gaicl_exit: + + g_arch_instruction_wunlock_src(dest); + + return result; /* TODO : si les informations complémentaires restent en place, compléter ! */ @@ -662,6 +692,46 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d /****************************************************************************** * * +* Paramètres : collec = collection à mettre à jour. * +* write = précise le type d'accès prévu (lecture/écriture). * +* lock = indique le sens du verrouillage à mener. * +* * +* Description : Met à disposition un encadrement des accès aux sources. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_arch_instruction_lock_unlock_sources(GArchInstruction *instr, bool write, bool lock) +{ +#ifndef NDEBUG + if (!lock) + g_atomic_int_dec_and_test(&instr->hold_from_access); +#endif + + if (write) + { + if (lock) g_rw_lock_writer_lock(&instr->from_access); + else g_rw_lock_writer_unlock(&instr->from_access); + } + else + { + if (lock) g_rw_lock_reader_lock(&instr->from_access); + else g_rw_lock_reader_unlock(&instr->from_access); + } + +#ifndef NDEBUG + if (lock) + g_atomic_int_inc(&instr->hold_from_access); +#endif + +} + + +/****************************************************************************** +* * * Paramètres : instr = instruction dont les informations sont à consulter. * * * * Description : Indique si l'instruction a une ou plusieurs origines. * @@ -674,6 +744,8 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d bool g_arch_instruction_has_sources(const GArchInstruction *instr) { + assert(g_atomic_int_get(&instr->hold_from_access) > 0); + return (instr->from_count > 0); } @@ -695,6 +767,8 @@ bool g_arch_instruction_has_sources(const GArchInstruction *instr) size_t g_arch_instruction_get_sources(const GArchInstruction *instr, GArchInstruction ***srcs, InstructionLinkType **types) { + assert(g_atomic_int_get(&instr->hold_from_access) > 0); + if (srcs != NULL) *srcs = instr->from; @@ -708,6 +782,46 @@ size_t g_arch_instruction_get_sources(const GArchInstruction *instr, GArchInstru /****************************************************************************** * * +* Paramètres : collec = collection à mettre à jour. * +* write = précise le type d'accès prévu (lecture/écriture). * +* lock = indique le sens du verrouillage à mener. * +* * +* Description : Met à disposition un encadrement des accès aux destinations. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_arch_instruction_lock_unlock_destinations(GArchInstruction *instr, bool write, bool lock) +{ +#ifndef NDEBUG + if (!lock) + g_atomic_int_dec_and_test(&instr->hold_to_access); +#endif + + if (write) + { + if (lock) g_rw_lock_writer_lock(&instr->to_access); + else g_rw_lock_writer_unlock(&instr->to_access); + } + else + { + if (lock) g_rw_lock_reader_lock(&instr->to_access); + else g_rw_lock_reader_unlock(&instr->to_access); + } + +#ifndef NDEBUG + if (lock) + g_atomic_int_inc(&instr->hold_to_access); +#endif + +} + + +/****************************************************************************** +* * * Paramètres : instr = instruction dont les informations sont à consulter. * * * * Description : Indique si l'instruction a une suite autre que la suivante. * @@ -720,8 +834,8 @@ size_t g_arch_instruction_get_sources(const GArchInstruction *instr, GArchInstru bool g_arch_instruction_has_destinations(const GArchInstruction *instr) { - /* FIXME !? */ - //return (instr->to_count > 1 || (instr->to_count == 1 && instr->to_types[0] != ILT_CALL)); + assert(g_atomic_int_get(&instr->hold_to_access) > 0); + return (instr->to_count > 0); } @@ -744,6 +858,8 @@ bool g_arch_instruction_has_destinations(const GArchInstruction *instr) size_t g_arch_instruction_get_destinations(const GArchInstruction *instr, GArchInstruction ***dests, InstructionLinkType **types, link_extra_info **info) { + assert(g_atomic_int_get(&instr->hold_to_access) > 0); + if (dests != NULL) *dests = instr->to; @@ -778,6 +894,8 @@ GArchInstruction *g_arch_instruction_get_given_destination(const GArchInstructio result = NULL; + assert(g_atomic_int_get(&instr->hold_to_access) > 0); + for (i = 0; i < instr->to_count && result == NULL; i++) if (instr->to_types[i] == type) result = instr->to[i]; diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 95d2e22..f26a240 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -189,12 +189,30 @@ void g_arch_instruction_link_with(GArchInstruction *, GArchInstruction *, Instru /* Change la nature d'un lien entre deux instructions. */ bool g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, InstructionLinkType, InstructionLinkType); +/* Met à disposition un encadrement des accès aux sources. */ +void g_arch_instruction_lock_unlock_sources(GArchInstruction *, bool, bool); + +#define g_arch_instruction_wlock_src(ins) g_arch_instruction_lock_unlock_sources(ins, true, true) +#define g_arch_instruction_wunlock_src(ins) g_arch_instruction_lock_unlock_sources(ins, true, false) + +#define g_arch_instruction_rlock_src(ins) g_arch_instruction_lock_unlock_sources(ins, false, true) +#define g_arch_instruction_runlock_src(ins) g_arch_instruction_lock_unlock_sources(ins, false, false) + /* Indique si l'instruction a une ou plusieurs origines. */ bool g_arch_instruction_has_sources(const GArchInstruction *); /* Fournit les origines d'une instruction donnée. */ size_t g_arch_instruction_get_sources(const GArchInstruction *, GArchInstruction ***, InstructionLinkType **); +/* Met à disposition un encadrement des accès aux destinations. */ +void g_arch_instruction_lock_unlock_destinations(GArchInstruction *, bool, bool); + +#define g_arch_instruction_wlock_dest(ins) g_arch_instruction_lock_unlock_destinations(ins, true, true) +#define g_arch_instruction_wunlock_dest(ins) g_arch_instruction_lock_unlock_destinations(ins, true, false) + +#define g_arch_instruction_rlock_dest(ins) g_arch_instruction_lock_unlock_destinations(ins, false, true) +#define g_arch_instruction_runlock_dest(ins) g_arch_instruction_lock_unlock_destinations(ins, false, false) + /* Indique si l'instruction a une suite autre que la suivante. */ bool g_arch_instruction_has_destinations(const GArchInstruction *); |