summaryrefslogtreecommitdiff
path: root/src/arch/instruction.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-04-20 12:07:19 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-04-20 12:07:19 (GMT)
commit59f319d9a6961a7424c7b32f49aa7ac1045a1d4c (patch)
treee9d62c684dd8d8f5e141b9332994041bd2371f9a /src/arch/instruction.c
parent8962a4e61411c8362d5f4be63496977164b886a8 (diff)
Protected all concurrent accesses to sources and destinations of instructions.
Diffstat (limited to 'src/arch/instruction.c')
-rw-r--r--src/arch/instruction.c130
1 files changed, 124 insertions, 6 deletions
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];