From 286878b36b5cf7a3f44251f62c94a57f0f29d3cf Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 9 May 2018 12:58:31 +0200 Subject: Handled the global work queue groups in a better way. --- src/analysis/loaded.c | 1 + src/core/Makefile.am | 3 +- src/core/core.c | 7 +-- src/core/queue.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++ src/core/queue.h | 52 +++++++++++++++++++++ src/glibext/delayed.c | 74 +++++++++++++---------------- src/glibext/delayed.h | 5 +- src/gui/panels/updating.c | 1 + src/main.c | 3 +- 9 files changed, 211 insertions(+), 50 deletions(-) create mode 100644 src/core/queue.c create mode 100644 src/core/queue.h 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 . + */ + + +#include "queue.h" + + +#include + + +#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 . + */ + + +#ifndef _CORE_QUEUE_H +#define _CORE_QUEUE_H + + +#include + + + +/** + * 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(); -- cgit v0.11.2-87-g4458