summaryrefslogtreecommitdiff
path: root/src/arch/instruction.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2017-01-27 23:22:49 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2017-01-27 23:22:49 (GMT)
commit2b8f655628652f3cfb61c8b82d4b54fbf3ed9869 (patch)
treeecc32e82287a3402542c6bb204618a523e775889 /src/arch/instruction.c
parent36a006b2ac60c0cc1a2e2bea00d88508294be7f0 (diff)
Avoided deadlocks in access to instruction sources and destinations.
Diffstat (limited to 'src/arch/instruction.c')
-rw-r--r--src/arch/instruction.c171
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;