summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2018-05-09 10:58:31 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2018-05-09 10:58:31 (GMT)
commit286878b36b5cf7a3f44251f62c94a57f0f29d3cf (patch)
treea38a8a349ae55797f9fe2a1c2e3fb20b37855136
parent3014f4f91f660dd7eaf80c5634c8ffa8fe3e95ec (diff)
Handled the global work queue groups in a better way.
-rw-r--r--src/analysis/loaded.c1
-rwxr-xr-xsrc/core/Makefile.am3
-rw-r--r--src/core/core.c7
-rw-r--r--src/core/queue.c115
-rw-r--r--src/core/queue.h52
-rw-r--r--src/glibext/delayed.c74
-rw-r--r--src/glibext/delayed.h5
-rw-r--r--src/gui/panels/updating.c1
-rw-r--r--src/main.c3
9 files changed, 211 insertions, 50 deletions
diff --git a/src/analysis/loaded.c b/src/analysis/loaded.c
index 1273ebd..5dd96a8 100644
--- a/src/analysis/loaded.c
+++ b/src/analysis/loaded.c
@@ -29,6 +29,7 @@
#include "loaded-int.h"
#include "../core/global.h"
+#include "../core/queue.h"
#include "../glibext/chrysamarshal.h"
#include "../glibext/gloadedpanel.h"
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 6e3132d..7acadea 100755
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -9,7 +9,8 @@ libcore_la_SOURCES = \
global.h global.c \
logs.h logs.c \
params.h params.c \
- processors.h processors.c
+ processors.h processors.c \
+ queue.h queue.c
libcore_la_LDFLAGS = $(LIBGTK_LIBS) $(LIBXML_LIBS)
diff --git a/src/core/core.c b/src/core/core.c
index 1b6b033..5e3a4d0 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -39,6 +39,7 @@
#include "global.h"
#include "params.h"
#include "processors.h"
+#include "queue.h"
#include "../analysis/db/keymgn.h"
#include "../common/io.h"
#include "../common/xdg.h"
@@ -63,7 +64,6 @@ bool load_all_basic_components(void)
{
static bool result = false; /* Bilan à retourner */
char *cfgdir; /* Répertoire de configuration */
- GWorkQueue *queue; /* Singleton pour tâches */
GContentExplorer *explorer; /* Explorateur de contenus */
GContentResolver *resolver; /* Résolveur de contenus */
@@ -96,8 +96,7 @@ bool load_all_basic_components(void)
result &= g_generic_config_read(get_main_configuration());
- queue = g_work_queue_new();
- set_work_queue(queue);
+ result &= init_global_works();
explorer = g_content_explorer_new();
set_current_content_explorer(explorer);
@@ -142,6 +141,8 @@ void unload_all_basic_components(void)
unload_processors_definitions();
+ exit_global_works();
+
g_generic_config_write(get_main_configuration());
unload_main_config_parameters();
diff --git a/src/core/queue.c b/src/core/queue.c
new file mode 100644
index 0000000..615e351
--- /dev/null
+++ b/src/core/queue.c
@@ -0,0 +1,115 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * queue.c - mise en place des mécanismes de traitements parallèles
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "queue.h"
+
+
+#include <assert.h>
+
+
+#include "global.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Met en place les mécanismes de traitements parallèles. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool init_global_works(void)
+{
+ GWorkQueue *queue; /* Singleton pour tâches */
+#ifndef NDEBUG
+ wgroup_id_t expected; /* Identifiant gloabl attendu */
+#endif
+
+ queue = g_work_queue_new();
+ set_work_queue(queue);
+
+#ifndef NDEBUG
+ expected = g_work_queue_define_work_group(queue);
+ assert(expected == DEFAULT_WORK_GROUP);
+#else
+ g_work_queue_define_work_group(queue);
+#endif
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Supprime les mécanismes de traitements parallèles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void exit_global_works(void)
+{
+ GWorkQueue *queue; /* Singleton pour tâches */
+
+ queue = get_work_queue();
+
+ g_object_unref(G_OBJECT(queue));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Attend que toutes les tâches de tout groupe soient traitées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void wait_for_all_global_works(void)
+{
+ GWorkQueue *queue; /* Singleton pour tâches */
+
+ static const wgroup_id_t group_ids[] = {
+ DEFAULT_WORK_GROUP
+ };
+
+ queue = get_work_queue();
+
+ g_work_queue_wait_for_all_completions(queue, group_ids, GLOBAL_WORK_GROUPS_COUNT);
+
+}
diff --git a/src/core/queue.h b/src/core/queue.h
new file mode 100644
index 0000000..1984fff
--- /dev/null
+++ b/src/core/queue.h
@@ -0,0 +1,52 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * queue.h - prototypes pour la mise en place des mécanismes de traitements parallèles
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _CORE_QUEUE_H
+#define _CORE_QUEUE_H
+
+
+#include <stdbool.h>
+
+
+
+/**
+ * Groupes d'exécution principaux.
+ */
+
+#define DEFAULT_WORK_GROUP 0
+
+#define GLOBAL_WORK_GROUPS_COUNT 1
+
+
+/* Met en place les mécanismes de traitements parallèles. */
+bool init_global_works(void);
+
+/* Supprime les mécanismes de traitements parallèles. */
+void exit_global_works(void);
+
+/* Attend que toutes les tâches de tout groupe soient traitées. */
+void wait_for_all_global_works(void);
+
+
+
+#endif /* _CORE_QUEUE_H */
diff --git a/src/glibext/delayed.c b/src/glibext/delayed.c
index 9d67a7c..9bac68a 100644
--- a/src/glibext/delayed.c
+++ b/src/glibext/delayed.c
@@ -175,7 +175,7 @@ static void g_work_queue_dispose(GWorkQueue *);
static void g_work_queue_finalize(GWorkQueue *);
/* Donne l'assurance de l'existence d'un groupe de travail. */
-static GWorkGroup *g_work_queue_ensure_group_exists(GWorkQueue *, wgroup_id_t);
+static bool g_work_queue_ensure_group_exists(GWorkQueue *, wgroup_id_t);
/* Fournit le groupe de travail correspondant à un identifiant. */
static GWorkGroup *g_work_queue_find_group_for_id(GWorkQueue *, wgroup_id_t);
@@ -682,13 +682,11 @@ static bool g_work_group_is_empty(GWorkGroup *group)
* son utilisation par l'appelant.
*
* Il doit donc logiquement y avoir un autre verrou en amont et,
- * comme à priori on ne devrait pas bloquer le groupe principal
- * pour un traitement particulier, on ajoute ici une simple vérification
- * de bonne pratique.
+ * comme à priori on ne devrait pas bloquer les groupes principaux
+ * pour un traitement particulier, cette procédure ne devrait concerner
+ * que des groupes dynamiques.
*/
- assert(group->id != DEFAULT_WORK_GROUP);
-
g_mutex_lock(&group->mutex);
result = dl_list_empty(group->works);
@@ -936,24 +934,26 @@ GWorkQueue *g_work_queue_new(void)
* *
* Description : Donne l'assurance de l'existence d'un groupe de travail. *
* *
-* Retour : - *
+* Retour : true si un nouveau groupe a été constitué, false sinon. *
* *
* Remarques : Le verrou d'accès doit être posé par l'appelant. *
* *
******************************************************************************/
-static GWorkGroup *g_work_queue_ensure_group_exists(GWorkQueue *queue, wgroup_id_t id)
+static bool g_work_queue_ensure_group_exists(GWorkQueue *queue, wgroup_id_t id)
{
- GWorkGroup *result; /* Groupe en place à renvoyer */
bool found; /* Bilan des recherches */
size_t i; /* Boucle de parcours */
+ GWorkGroup *group; /* Groupe à consulter */
+
+ assert(!g_mutex_trylock(&queue->mutex));
found = false;
for (i = 0; i < queue->groups_count && !found; i++)
{
- result = queue->groups[i];
- found = (g_work_group_get_id(result) == id);
+ group = queue->groups[i];
+ found = (g_work_group_get_id(group) == id);
}
if (!found)
@@ -962,12 +962,12 @@ static GWorkGroup *g_work_queue_ensure_group_exists(GWorkQueue *queue, wgroup_id
queue->groups = (GWorkGroup **)realloc(queue->groups,
queue->groups_count * sizeof(GWorkGroup *));
- result = g_work_group_new(id);
- queue->groups[queue->groups_count - 1] = result;
+ group = g_work_group_new(id);
+ queue->groups[queue->groups_count - 1] = group;
}
- return result;
+ return !found;
}
@@ -987,12 +987,16 @@ static GWorkGroup *g_work_queue_ensure_group_exists(GWorkQueue *queue, wgroup_id
wgroup_id_t g_work_queue_define_work_group(GWorkQueue *queue)
{
wgroup_id_t result; /* Valeur à retourner */
+ bool created; /* Bilan d'une tentative */
g_mutex_lock(&queue->mutex);
- result = ++queue->generator;
-
- g_work_queue_ensure_group_exists(queue, result);
+ do
+ {
+ result = queue->generator++;
+ created = g_work_queue_ensure_group_exists(queue, result);
+ }
+ while (!created);
g_mutex_unlock(&queue->mutex);
@@ -1072,13 +1076,8 @@ void g_work_queue_schedule_work(GWorkQueue *queue, GDelayedWork *work, wgroup_id
{
GWorkGroup *group; /* Groupe de travail à attendre*/
- g_mutex_lock(&queue->mutex);
-
- group = g_work_queue_ensure_group_exists(queue, id);
-
- g_object_ref(G_OBJECT(group));
-
- g_mutex_unlock(&queue->mutex);
+ group = g_work_queue_find_group_for_id(queue, id);
+ assert(group != NULL);
g_work_group_schedule(group, work);
@@ -1188,7 +1187,9 @@ void g_work_queue_wait_for_completion(GWorkQueue *queue, wgroup_id_t id)
/******************************************************************************
* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
+* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail.*
+* gb_ids = identifiants de groupes globaux. *
+* gb_count = nombre de ces groupes globaux. *
* *
* Description : Attend que toutes les tâches de tout groupe soient traitées. *
* *
@@ -1198,36 +1199,29 @@ void g_work_queue_wait_for_completion(GWorkQueue *queue, wgroup_id_t id)
* *
******************************************************************************/
-void g_work_queue_wait_for_all_completions(GWorkQueue *queue)
+void g_work_queue_wait_for_all_completions(GWorkQueue *queue, const wgroup_id_t *gb_ids, size_t gb_count)
{
- GWorkGroup *def_group; /* Groupe de travail par défaut*/
+ size_t i; /* Boucle de parcours */
g_mutex_lock(&queue->mutex);
- /**
- * Récupération du groupe par défaut.
- */
-
- def_group = g_work_queue_ensure_group_exists(queue, DEFAULT_WORK_GROUP);
-
- g_object_ref(G_OBJECT(def_group));
-
wait_again:
/**
* Attente d'éventuels groupes isolés.
*/
- while (queue->groups_count > 1)
+ while (queue->groups_count > gb_count)
g_cond_wait(&queue->wait_all, &queue->mutex);
g_mutex_unlock(&queue->mutex);
/**
- * Attente du groupe principal.
+ * Attente des groupes principaux.
*/
- g_work_queue_wait_for_completion(queue, DEFAULT_WORK_GROUP);
+ for (i = 0; i < gb_count; i++)
+ g_work_queue_wait_for_completion(queue, gb_ids[i]);
/**
* Si le groupe par défaut a généré de nouveaux groupes, on recommence !
@@ -1235,13 +1229,11 @@ void g_work_queue_wait_for_all_completions(GWorkQueue *queue)
g_mutex_lock(&queue->mutex);
- if (queue->groups_count > 1)
+ if (queue->groups_count > gb_count)
goto wait_again;
g_mutex_unlock(&queue->mutex);
- g_object_unref(G_OBJECT(def_group));
-
}
diff --git a/src/glibext/delayed.h b/src/glibext/delayed.h
index 340a298..c22cc5a 100644
--- a/src/glibext/delayed.h
+++ b/src/glibext/delayed.h
@@ -82,9 +82,6 @@ typedef struct _GWorkQueueClass GWorkQueueClass;
/* Identifiant unique pour groupe de travail */
typedef unsigned long long wgroup_id_t;
-/* Groupe d'exécution par défaut */
-#define DEFAULT_WORK_GROUP 0
-
/* Indique le type défini pour le gestionnaire des travaux différés. */
GType g_work_queue_get_type(void);
@@ -108,7 +105,7 @@ bool g_work_queue_is_empty(GWorkQueue *, wgroup_id_t);
void g_work_queue_wait_for_completion(GWorkQueue *, wgroup_id_t);
/* Attend que toutes les tâches de tout groupe soient traitées. */
-void g_work_queue_wait_for_all_completions(GWorkQueue *);
+void g_work_queue_wait_for_all_completions(GWorkQueue *, const wgroup_id_t *, size_t);
/* Etudie le besoin d'attendre d'avantage de prochaines tâches. */
diff --git a/src/gui/panels/updating.c b/src/gui/panels/updating.c
index 800161c..824898a 100644
--- a/src/gui/panels/updating.c
+++ b/src/gui/panels/updating.c
@@ -29,6 +29,7 @@
#include "updating-int.h"
#include "../../core/global.h"
+#include "../../core/queue.h"
#include "../../glibext/delayed-int.h"
#include "../../glibext/signal.h"
diff --git a/src/main.c b/src/main.c
index 018651a..583e00c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -39,6 +39,7 @@
#include "core/global.h"
#include "core/logs.h"
#include "core/params.h"
+#include "core/queue.h"
#include "glibext/delayed.h"
#include "gui/editor.h"
#include "gui/core/core.h"
@@ -343,7 +344,7 @@ int main(int argc, char **argv)
result = open_binaries(argv + optind, argc - optind);
if (batch_mode)
- g_work_queue_wait_for_all_completions(get_work_queue());
+ wait_for_all_global_works();
else
gtk_main();