--- rpl/src/gestion_variables_partagees.c 2011/04/11 13:02:16 1.16.2.1 +++ rpl/src/gestion_variables_partagees.c 2020/01/10 11:15:43 1.72 @@ -1,7 +1,7 @@ /* ================================================================================ - RPL/2 (R) version 4.0.22 - Copyright (C) 1989-2011 Dr. BERTRAND Joël + RPL/2 (R) version 4.1.32 + Copyright (C) 1989-2020 Dr. BERTRAND Joël This file is part of RPL/2. @@ -25,6 +25,95 @@ /* ================================================================================ + Routine de gestion du cache des objets +================================================================================ + Entrée : +-------------------------------------------------------------------------------- + Sortie : +-------------------------------------------------------------------------------- + Effets de bords : néant +================================================================================ +*/ + +static inline struct_arbre_variables_partagees * +allocation_noeud_partage(struct_processus *s_etat_processus) +{ + struct_arbre_variables_partagees *objet; + + if ((*s_etat_processus).pointeur_variables_partagees_noeud > 0) + { + objet = (*s_etat_processus).variables_partagees_noeud + [--(*s_etat_processus).pointeur_variables_partagees_noeud]; + } + else + { + objet = malloc(sizeof(struct_arbre_variables_partagees)); + } + + return(objet); +} + +static inline void +liberation_noeud_partage(struct_processus *s_etat_processus, + struct_arbre_variables_partagees *objet) +{ + if ((*s_etat_processus).pointeur_variables_partagees_noeud < TAILLE_CACHE) + { + (*s_etat_processus).variables_partagees_noeud + [(*s_etat_processus).pointeur_variables_partagees_noeud++] = + objet; + } + else + { + free(objet); + } + + return; +} + +static inline struct_arbre_variables_partagees ** +allocation_tableau_noeuds_partages(struct_processus *s_etat_processus) +{ + struct_arbre_variables_partagees **objet; + + if ((*s_etat_processus).pointeur_variables_tableau_noeuds_partages > 0) + { + objet = (*s_etat_processus).variables_tableau_noeuds_partages + [--(*s_etat_processus) + .pointeur_variables_tableau_noeuds_partages]; + } + else + { + objet = malloc(((size_t) (*s_etat_processus) + .nombre_caracteres_variables) + * sizeof(struct_arbre_variables_partagees *)); + } + + return(objet); +} + +static inline void +liberation_tableau_noeuds_partages(struct_processus *s_etat_processus, + struct_arbre_variables_partagees **objet) +{ + if ((*s_etat_processus).pointeur_variables_tableau_noeuds_partages + < TAILLE_CACHE) + { + (*s_etat_processus).variables_tableau_noeuds_partages + [(*s_etat_processus) + .pointeur_variables_tableau_noeuds_partages++] = objet; + } + else + { + free(objet); + } + + return; +} + + +/* +================================================================================ Routine de création d'une nouvelle variable partagee ================================================================================ Entrée : @@ -39,431 +128,736 @@ logical1 creation_variable_partagee(struct_processus *s_etat_processus, struct_variable_partagee *s_variable) { - struct_variable_partagee *s_nouvelle_base; + int i; - long i; + struct_arbre_variables_partagees *l_variable_courante; - (*(*s_etat_processus).s_liste_variables_partagees).nombre_variables++; + struct_liste_variables_partagees *l_nouvel_element; - if ((*(*s_etat_processus).s_liste_variables_partagees).nombre_variables > - (*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables_allouees) + unsigned char *ptr; + + // Ajout de la variable en tête de la liste des variables partagées + + if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_partagees))) + == NULL) { - // La nouvelle variable partagée ne tient pas dans la table existante. - // Il convient donc d'en augmenter la taille. + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } - if ((*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables_allouees == 0) - { - (*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables_allouees = (*(*s_etat_processus) - .s_liste_variables_partagees).nombre_variables; - } - else + if (((*l_nouvel_element).variable = malloc(sizeof( + struct_variable_partagee))) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } + + (*(*l_nouvel_element).variable) = (*s_variable); + (*l_nouvel_element).pid = getpid(); + (*l_nouvel_element).tid = pthread_self(); + + if (pthread_mutex_lock(&mutex_liste_variables_partagees) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } + + (*l_nouvel_element).suivant = (*(*s_etat_processus) + .l_liste_variables_partagees); + (*l_nouvel_element).precedent = NULL; + + if ((*(*s_etat_processus).l_liste_variables_partagees) != NULL) + { + (**(*s_etat_processus).l_liste_variables_partagees).precedent + = l_nouvel_element; + } + + (*(*s_etat_processus).l_liste_variables_partagees) = l_nouvel_element; + + // Ajout de la variable à la feuille de l'arbre des variables partagees + + if ((*(*s_etat_processus).s_arbre_variables_partagees) == NULL) + { + if (((*(*s_etat_processus).s_arbre_variables_partagees) = + allocation_noeud_partage(s_etat_processus)) == NULL) { - while((*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables > (*(*s_etat_processus) - .s_liste_variables_partagees).nombre_variables_allouees) + if (pthread_mutex_unlock(&mutex_liste_variables_partagees) != 0) { - (*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables_allouees *= 2; + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); } + + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); } - if ((s_nouvelle_base = realloc((struct_variable_partagee *) - (*(*s_etat_processus).s_liste_variables_partagees).table, - (*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables_allouees * - sizeof(struct_variable_partagee))) == NULL) + (**(*s_etat_processus).s_arbre_variables_partagees).feuille = NULL; + (**(*s_etat_processus).s_arbre_variables_partagees) + .noeuds_utilises = 0; + (**(*s_etat_processus).s_arbre_variables_partagees).indice_tableau_pere + = -1; + (**(*s_etat_processus).s_arbre_variables_partagees).noeud_pere = NULL; + INITIALISATION_MUTEX((**(*s_etat_processus).s_arbre_variables_partagees) + .mutex_feuille); + + if (((**(*s_etat_processus).s_arbre_variables_partagees).noeuds = + allocation_tableau_noeuds_partages(s_etat_processus)) == NULL) { + if (pthread_mutex_unlock(&mutex_liste_variables_partagees) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; - (*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables--; return(d_erreur); } - (*(*s_etat_processus).s_liste_variables_partagees).table = - s_nouvelle_base; + for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++) + { + (**(*s_etat_processus).s_arbre_variables_partagees).noeuds[i] = + NULL; + } } - /* - * Positionnement de la variable partagée au bon endroit - */ + l_variable_courante = (*(*s_etat_processus).s_arbre_variables_partagees); + ptr = (*s_variable).nom; - if ((*(*s_etat_processus).s_liste_variables_partagees).nombre_variables - == 1) + if (pthread_mutex_lock(&((*l_variable_courante).mutex_feuille)) != 0) { - (*(*s_etat_processus).s_liste_variables_partagees).table[0] - = (*s_variable); + if (pthread_mutex_unlock(&mutex_liste_variables_partagees) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } + + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); } - else + + while((*ptr) != d_code_fin_chaine) { - for(i = (*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables - 2; i >= 0; i--) + BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0, + uprintf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom, + *ptr)); + + if ((*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]] == NULL) { - if (strcmp((*s_variable).nom, (*(*s_etat_processus) - .s_liste_variables_partagees).table[i].nom) < 0) + // Le noeud n'existe pas encore, on le crée et on le marque + // comme utilisé dans la structure parente. + + if (((*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]] = + allocation_noeud_partage(s_etat_processus)) == NULL) { - (*(*s_etat_processus).s_liste_variables_partagees).table[i + 1] - = (*(*s_etat_processus).s_liste_variables_partagees) - .table[i]; + if (pthread_mutex_unlock(&mutex_liste_variables_partagees) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } + + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); } - else + + (*l_variable_courante).noeuds_utilises++; + + // La feuille est par défaut vide et aucun élément du tableau noeuds + // (les branches qui peuvent être issues de ce nouveau noeud) + // n'est encore utilisée. + + (*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).feuille = NULL; + (*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises = 0; + + // Le champ noeud_pere de la structure créée pointe sur + // la structure parente et l'indice tableau_pere correspond à la + // position réelle dans le tableau noeuds[] de la structure parente + // du noeud courant. Cette valeur sera utilisée lors de la + // destruction du noeud pour annuler le pointeur contenu dans + // le tableau noeuds[] de la structure parente. + + (*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).noeud_pere = + l_variable_courante; + (*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]) + .indice_tableau_pere = (*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]; + INITIALISATION_MUTEX((*(*l_variable_courante).noeuds + [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]]) + .mutex_feuille); + + // Allocation du tableau noeuds[] et initialisation à zéro de + // tous les pointeurs. + + if (((*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).noeuds = + allocation_tableau_noeuds_partages(s_etat_processus)) + == NULL) + { + if (pthread_mutex_unlock(&mutex_liste_variables_partagees) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } + + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } + + for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++) { - break; + (*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).noeuds[i] + = NULL; } } - (*(*s_etat_processus).s_liste_variables_partagees).table[i + 1] - = (*s_variable); + if (pthread_mutex_lock(&((*(*l_variable_courante).noeuds + [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]]) + .mutex_feuille)) != 0) + { + if (pthread_mutex_unlock(&mutex_liste_variables_partagees) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } + + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } + + if (pthread_mutex_unlock(&((*l_variable_courante).mutex_feuille)) != 0) + { + if (pthread_mutex_unlock(&mutex_liste_variables_partagees) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } + + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } + + l_variable_courante = (*l_variable_courante).noeuds + [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]]; + ptr++; + } + + if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_partagees))) + == NULL) + { + if (pthread_mutex_unlock(&mutex_liste_variables_partagees) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } + + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } + + // Dans la feuille de l'arbre des variables partagées, on ne balaie + // les variables que dans l'ordre. Le champ 'reference' est alors utilisé + // pour sauvegarder une référence vers la liste des variables partagées + // pour pouvoir purger l'élément en cas de besoin. + + (*l_nouvel_element).suivant = (*l_variable_courante).feuille; + (*l_nouvel_element).precedent = NULL; + + if ((*l_nouvel_element).suivant != NULL) + { + (*(*l_nouvel_element).suivant).precedent = l_nouvel_element; + } + + (*l_nouvel_element).reference = + (*(*s_etat_processus).l_liste_variables_partagees); + (*l_nouvel_element).variable = (**(*s_etat_processus) + .l_liste_variables_partagees).variable; + (*l_variable_courante).feuille = l_nouvel_element; + (*l_nouvel_element).feuille = l_variable_courante; + + if (pthread_mutex_unlock(&((*l_variable_courante).mutex_feuille)) != 0) + { + if (pthread_mutex_unlock(&mutex_liste_variables_partagees) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } + + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); } - return d_absence_erreur; + if (pthread_mutex_unlock(&mutex_liste_variables_partagees) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } + + return(d_absence_erreur); } /* ================================================================================ - Procédure de retrait d'une variable partagee de la base + Routine de recherche d'une variable partagée ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- - Effets de bord : néant + Effets de bords : positionne le mutex sur la variable partagée ================================================================================ */ -logical1 -retrait_variable_partagee(struct_processus *s_etat_processus, - unsigned char *nom_variable, union_position_variable position) +struct_liste_variables_partagees * +recherche_variable_partagee(struct_processus *s_etat_processus, + unsigned char *nom_variable, union_position_variable position, + unsigned char origine) { - struct_variable_partagee *s_nouvelle_base; + int pointeur; - logical1 erreur; + struct_arbre_variables_partagees *l_variable_courante; + struct_liste_variables_partagees *l_element_courant; - unsigned long position_courante; - unsigned long position_supprimee; + unsigned char *ptr; - if (recherche_variable_partagee(s_etat_processus, nom_variable, - position, ((*s_etat_processus).mode_execution_programme == 'Y') - ? 'P' : 'E') == d_vrai) + l_variable_courante = (*(*s_etat_processus).s_arbre_variables_partagees); + ptr = nom_variable; + + if (l_variable_courante == NULL) { - if ((*(*s_etat_processus).s_liste_variables_partagees).nombre_variables - < ((*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables_allouees / 2)) - { - (*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables_allouees /= 2; + (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + return(NULL); + } - if ((s_nouvelle_base = realloc((struct_variable_partagee *) - (*(*s_etat_processus).s_liste_variables_partagees).table, - (*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables_allouees * - sizeof(struct_variable_partagee))) == NULL) - { - (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; - return(d_erreur); - } + if (pthread_mutex_lock(&((*l_variable_courante).mutex_feuille)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(NULL); + } - (*(*s_etat_processus).s_liste_variables_partagees).table = - s_nouvelle_base; + while((*ptr) != d_code_fin_chaine) + { + pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr]; + + if (pointeur < 0) + { + // Caractère hors de l'alphabet des variables + + pthread_mutex_unlock(&((*l_variable_courante).mutex_feuille)); + (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + return(NULL); } - position_supprimee = (*(*s_etat_processus) - .s_liste_variables_partagees).position_variable; + if ((*l_variable_courante).noeuds[pointeur] == NULL) + { + // Le chemin de la variable candidate n'existe pas. - liberation(s_etat_processus, (*(*s_etat_processus) - .s_liste_variables_partagees).table[position_supprimee].objet); - free((*(*s_etat_processus).s_liste_variables_partagees) - .table[position_supprimee].nom); + pthread_mutex_unlock(&((*l_variable_courante).mutex_feuille)); + (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + return(NULL); + } - (*(*s_etat_processus).s_liste_variables_partagees).nombre_variables--; + if (pthread_mutex_lock(&((*(*l_variable_courante).noeuds[pointeur]) + .mutex_feuille)) != 0) + { + pthread_mutex_unlock(&((*l_variable_courante).mutex_feuille)); + (*s_etat_processus).erreur_systeme = d_es_processus; + return(NULL); + } - for(position_courante = position_supprimee; position_courante < - (*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables; position_courante++) + if (pthread_mutex_unlock(&((*l_variable_courante).mutex_feuille)) != 0) { - (*(*s_etat_processus).s_liste_variables_partagees).table - [position_courante] = (*(*s_etat_processus) - .s_liste_variables_partagees).table[position_courante + 1]; + (*s_etat_processus).erreur_systeme = d_es_processus; + return(NULL); } - erreur = d_absence_erreur; + l_variable_courante = (*l_variable_courante).noeuds[pointeur]; + ptr++; } - else + + if ((*l_variable_courante).feuille != NULL) { - erreur = d_erreur; - (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + // Il existe au moins une variable partagée du nom requis. + + l_element_courant = (*l_variable_courante).feuille; + + while(l_element_courant != NULL) + { + if ((*(*l_element_courant).variable).origine == 'P') + { + if (((*(*l_element_courant).variable).variable_partagee.adresse + == position.adresse) && + ((*(*l_element_courant).variable).origine == origine)) + { + if (pthread_mutex_lock(&((*(*l_element_courant).variable) + .mutex)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(NULL); + } + + if (pthread_mutex_unlock(&((*l_variable_courante) + .mutex_feuille)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(NULL); + } + + (*s_etat_processus).pointeur_variable_partagee_courante + = (*l_element_courant).variable; + return(l_element_courant); + } + } + else + { + if (((*(*l_element_courant).variable).variable_partagee.pointeur + == position.pointeur) && + ((*(*l_element_courant).variable).origine == origine)) + { + if (pthread_mutex_lock(&((*(*l_element_courant).variable) + .mutex)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(NULL); + } + + if (pthread_mutex_unlock(&((*l_variable_courante) + .mutex_feuille)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(NULL); + } + + (*s_etat_processus).pointeur_variable_partagee_courante + = (*l_element_courant).variable; + return(l_element_courant); + } + } + + l_element_courant = (*l_element_courant).suivant; + } } - return erreur; + if (pthread_mutex_unlock(&((*l_variable_courante).mutex_feuille)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(NULL); + } + + (*s_etat_processus).pointeur_variable_statique_courante = NULL; + return(NULL); } /* ================================================================================ - Procédure de recherche d'une variable partagee par son nom dans la base + Routine de retrait d'une variable partagée ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- - Effets de bord : néant + Effets de bords : néant ================================================================================ */ logical1 -recherche_variable_partagee(struct_processus *s_etat_processus, - unsigned char *nom_variable, union_position_variable position, - unsigned char origine) +retrait_variable_partagee(struct_processus *s_etat_processus, + unsigned char *nom_variable, union_position_variable position) { - logical1 existence_variable; + struct_liste_variables_partagees *l_element_a_supprimer; + struct_liste_variables_partagees *l_element_liste_a_supprimer; - long difference; - long difference_inferieure; - long difference_superieure; - - unsigned long borne_inferieure; - unsigned long borne_superieure; - unsigned long moyenne; - unsigned long nombre_iterations_maximal; - unsigned long ordre_iteration; + logical1 erreur; - if ((*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables == 0) + if ((l_element_a_supprimer = recherche_variable_partagee(s_etat_processus, + nom_variable, position, ((*s_etat_processus) + .mode_execution_programme == 'Y') ? 'P' : 'E')) != NULL) { - (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; - return d_faux; - } + if (pthread_mutex_lock(&mutex_liste_variables_partagees) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } - ordre_iteration = 0; - nombre_iterations_maximal = ((unsigned long) - (log((*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables) / log(2))) + 2; + // (*s_etat_processus).pointeur_variable_partagee_courante + // pointe sur la variable à éliminer. Cette variable est celle qui + // est présente dans l'une des feuilles statiques de l'arbre des + // variables. - borne_inferieure = 0; - borne_superieure = (*(*s_etat_processus).s_liste_variables_partagees) - .nombre_variables - 1; + l_element_liste_a_supprimer = (*l_element_a_supprimer).reference; - do - { - moyenne = (borne_inferieure + borne_superieure) / 2; - ordre_iteration++; + // Suppression de la liste des variables statiques - if ((2 * ((unsigned long) ((borne_inferieure + borne_superieure) / 2))) - == (borne_inferieure + borne_superieure)) + if ((*l_element_liste_a_supprimer).precedent != NULL) { - difference = strcmp(nom_variable, - (*(*s_etat_processus).s_liste_variables_partagees) - .table[moyenne].nom); + // L'élément à supprimer n'est pas le premier de la liste. - if (difference != 0) + (*(*l_element_liste_a_supprimer).precedent).suivant = + (*l_element_liste_a_supprimer).suivant; + + if ((*l_element_liste_a_supprimer).suivant != NULL) { - if (difference > 0) - { - borne_inferieure = moyenne; - } - else - { - borne_superieure = moyenne; - } + // Il y a un élément suivant. On le chaîne. + (*(*l_element_liste_a_supprimer).suivant).precedent = NULL; } } else { - difference_inferieure = strcmp(nom_variable, - (*(*s_etat_processus).s_liste_variables_partagees).table - [moyenne].nom); - difference_superieure = strcmp(nom_variable, - (*(*s_etat_processus).s_liste_variables_partagees).table - [moyenne + 1].nom); + // L'élement est le premier de la liste. S'il y a un élément + // suivant, on le chaîne. - if (difference_inferieure == 0) + if ((*l_element_liste_a_supprimer).suivant != NULL) { - difference = 0; + (*(*l_element_liste_a_supprimer).suivant).precedent = NULL; } - else if (difference_superieure == 0) - { - difference = 0; - moyenne++; - } - else - { - difference = difference_inferieure; - if (difference > 0) - { - borne_inferieure = moyenne; - } - else - { - borne_superieure = moyenne; - } - } + (*(*s_etat_processus).l_liste_variables_partagees) = + (*l_element_liste_a_supprimer).suivant; } - } while((difference != 0) && - (ordre_iteration <= nombre_iterations_maximal)); - if (ordre_iteration > nombre_iterations_maximal) - { - existence_variable = d_faux; - (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; - } - else - { - // Reste à rechercher la variable déclarée à la position 'position'... + free(l_element_liste_a_supprimer); - if ((*(*s_etat_processus).s_liste_variables_partagees).table[moyenne] - .origine == 'P') + // Suppression depuis la feuille statique. Le champ 'precedent' ne sert + // pas car la liste est simplement chaînée. + + if ((*l_element_a_supprimer).precedent != NULL) { - if (((*(*s_etat_processus).s_liste_variables_partagees) - .table[moyenne].variable_partagee.adresse == - position.adresse) && ((*(*s_etat_processus) - .s_liste_variables_partagees).table[moyenne] - .origine == origine)) + // L'élément n'est pas le premier de la liste. + + (*(*l_element_a_supprimer).precedent).suivant = + (*l_element_a_supprimer).suivant; + + if ((*l_element_a_supprimer).suivant != NULL) { - existence_variable = d_vrai; + (*(*l_element_a_supprimer).suivant).precedent = + (*l_element_a_supprimer).precedent; } else { - existence_variable = d_faux; + (*(*l_element_a_supprimer).precedent).suivant = NULL; } } else { - if (((*(*s_etat_processus).s_liste_variables_partagees) - .table[moyenne].variable_partagee.pointeur == - position.pointeur) && ((*(*s_etat_processus) - .s_liste_variables_partagees).table[moyenne] - .origine == origine)) - { - existence_variable = d_vrai; - } - else + // L'élément est le premier de la liste. + + if ((*l_element_a_supprimer).suivant != NULL) { - existence_variable = d_faux; + (*(*l_element_a_supprimer).suivant).precedent = NULL; } + + (*(*l_element_a_supprimer).feuille).feuille + = (*l_element_a_supprimer).suivant; } - if (existence_variable == d_faux) + liberation(s_etat_processus, (*(*l_element_a_supprimer).variable) + .objet); + free((*(*l_element_a_supprimer).variable).nom); + pthread_mutex_unlock(&((*(*l_element_a_supprimer).variable).mutex)); + pthread_mutex_destroy(&((*(*l_element_a_supprimer).variable).mutex)); + free((*l_element_a_supprimer).variable); + free(l_element_a_supprimer); + + if (pthread_mutex_unlock(&mutex_liste_variables_partagees) != 0) { - // On rembobine. + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } - if (moyenne > 0) - { - while(strcmp(nom_variable, (*(*s_etat_processus) - .s_liste_variables_partagees).table[moyenne - 1].nom) - == 0) - { - moyenne--; + erreur = d_absence_erreur; + } + else + { + erreur = d_erreur; + (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + } + + return(erreur); +} - if (moyenne == 0) - { - break; - } - } - } - // Un petit test pour voir si le premier élément du tableau - // peut correspondre au critère de recherche. +/* +================================================================================ + Routine de retrait des variables partagées +================================================================================ + Entrée : +-------------------------------------------------------------------------------- + Sortie : +-------------------------------------------------------------------------------- + Effets de bords : néant +================================================================================ +*/ + +// Cette routine libère toutes les variables partagées de niveau non +// nul, donc attachées à une expression et non un programme. - existence_variable = d_faux; +logical1 +retrait_variables_partagees_locales(struct_processus *s_etat_processus) +{ + struct_liste_variables_partagees *l_element_courant; + struct_liste_variables_partagees *l_element_suivant; + + unsigned char registre_mode_execution; + + if (pthread_mutex_lock(&mutex_liste_variables_partagees) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } - if (strcmp((*(*s_etat_processus).s_liste_variables_partagees).table - [moyenne].nom, nom_variable) == 0) + registre_mode_execution = (*s_etat_processus).mode_execution_programme; + l_element_courant = (*(*s_etat_processus).l_liste_variables_partagees); + + while(l_element_courant != NULL) + { + l_element_suivant = (*l_element_courant).suivant; + + (*s_etat_processus).mode_execution_programme = + ((*(*l_element_courant).variable).origine == 'P') ? 'Y' : 'N'; + + if (((*(*l_element_courant).variable).niveau > 0) && + ((*l_element_courant).pid == getpid()) && + (pthread_equal((*l_element_courant).tid, pthread_self()) != 0)) + { + if (retrait_variable_partagee(s_etat_processus, + (*(*l_element_courant).variable).nom, + (*(*l_element_courant).variable).variable_partagee) + == d_erreur) { - if ((*(*s_etat_processus).s_liste_variables_partagees).table - [moyenne].origine == 'P') + if (pthread_mutex_unlock(&mutex_liste_variables_partagees) != 0) { - if (((*(*s_etat_processus).s_liste_variables_partagees) - .table[moyenne].variable_partagee.adresse - == position.adresse) && - ((*(*s_etat_processus).s_liste_variables_partagees) - .table[moyenne].origine == origine)) - { - existence_variable = d_vrai; - } - } - else - { - if (((*(*s_etat_processus).s_liste_variables_partagees) - .table[moyenne].variable_partagee.pointeur - == position.pointeur) && - ((*(*s_etat_processus).s_liste_variables_partagees) - .table[moyenne].origine == origine)) - { - existence_variable = d_vrai; - } + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); } + + (*s_etat_processus).mode_execution_programme = + registre_mode_execution; + return(d_erreur); } + } - // Puis on balaye dans le sens croissant. + l_element_courant = l_element_suivant; + } - if (((moyenne + 1) < (*(*s_etat_processus) - .s_liste_variables_partagees).nombre_variables) - && (existence_variable == d_faux)) - { - while(strcmp((*(*s_etat_processus) - .s_liste_variables_partagees).table[moyenne + 1].nom, - nom_variable) == 0) - { - moyenne++; + (*s_etat_processus).mode_execution_programme = registre_mode_execution; - if ((*(*s_etat_processus).s_liste_variables_partagees) - .table[moyenne].origine == 'P') - { - if (((*(*s_etat_processus).s_liste_variables_partagees) - .table[moyenne].variable_partagee.adresse == - position.adresse) && ((*(*s_etat_processus) - .s_liste_variables_partagees) - .table[moyenne].origine == origine)) - { - existence_variable = d_vrai; - break; - } - } - else - { - if (((*(*s_etat_processus).s_liste_variables_partagees) - .table[moyenne].variable_partagee.pointeur == - position.pointeur) && ((*(*s_etat_processus) - .s_liste_variables_partagees) - .table[moyenne].origine == origine)) - { - existence_variable = d_vrai; - break; - } - } + if (pthread_mutex_unlock(&mutex_liste_variables_partagees) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(d_erreur); + } - if ((moyenne + 1) >= (*(*s_etat_processus) - .s_liste_variables_partagees).nombre_variables) - { - break; - } - } - } - } + return(d_absence_erreur); +} + + +/* +================================================================================ + Routine de libération de l'arbre des variables partagées +================================================================================ + Entrée : +-------------------------------------------------------------------------------- + Sortie : +-------------------------------------------------------------------------------- + Effets de bords : positionne le mutex sur la variable partagée +================================================================================ +*/ + +void +liberation_arbre_variables_partagees(struct_processus *s_etat_processus, + struct_arbre_variables_partagees *arbre) +{ + int i; + + struct_liste_variables_partagees *l_element_partage_courant; + struct_liste_variables_partagees *l_element_partage_suivant; + + // Libération de l'arbre des variables. Le contenu des variables n'est + // pas détruit par cette opération, il sera détruit lors de la libération + // de la liste des variables par niveau. - (*(*s_etat_processus).s_liste_variables_partagees).position_variable - = moyenne; + if (arbre == NULL) + { + return; } - /* - * Si la variable partagée n'existe pas, elle a été rendue privée par un - * thread concurrent. Il faut donc l'enlever de la table des variables - * du thread courant. - */ + if (pthread_mutex_lock(&((*arbre).mutex_feuille)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } - if (existence_variable == d_faux) + l_element_partage_courant = (*arbre).feuille; + + while(l_element_partage_courant != NULL) { - if (retrait_variable(s_etat_processus, nom_variable, 'L') == d_faux) + l_element_partage_suivant = (*l_element_partage_courant).suivant; + + if (pthread_mutex_lock(&((*(*l_element_partage_courant).variable) + .mutex)) != 0) { - return d_faux; + (*s_etat_processus).erreur_systeme = d_es_processus; + return; } + + free((*(*l_element_partage_courant).variable).nom); + liberation(s_etat_processus, (*(*l_element_partage_courant) + .variable).objet); + free((*l_element_partage_courant).variable); + + if (pthread_mutex_unlock(&((*(*l_element_partage_courant).variable) + .mutex)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + + if (pthread_mutex_destroy(&((*(*l_element_partage_courant).variable) + .mutex)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + + free(l_element_partage_courant); + + l_element_partage_courant = l_element_partage_suivant; + } + + for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++) + { + if ((*arbre).noeuds[i] != NULL) + { + liberation_arbre_variables_partagees(s_etat_processus, + (*arbre).noeuds[i]); + (*arbre).noeuds[i] = NULL; + } + } + + liberation_tableau_noeuds_partages(s_etat_processus, (*arbre).noeuds); + liberation_noeud_partage(s_etat_processus, arbre); + + if (pthread_mutex_unlock(&((*arbre).mutex_feuille)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + + if (pthread_mutex_destroy(&((*arbre).mutex_feuille)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; } - return existence_variable; + arbre = NULL; + return; } // vim: ts=4