--- rpl/src/gestion_objets.c 2010/01/26 15:22:44 1.1.1.1 +++ rpl/src/gestion_objets.c 2010/08/17 11:59:27 1.37 @@ -1,6 +1,6 @@ /* ================================================================================ - RPL/2 (R) version 4.0.9 + RPL/2 (R) version 4.0.18 Copyright (C) 1989-2010 Dr. BERTRAND Joël This file is part of RPL/2. @@ -20,12 +20,12 @@ */ -#include "rpl.conv.h" +#include "rpl-conv.h" /* ================================================================================ - Routine de gestion du nombre d'occurrences comme grandeur atomique + Routines de gestion du nombre d'occurrences comme grandeur atomique ================================================================================ entrées : structure sur l'état du processus et objet à afficher -------------------------------------------------------------------------------- @@ -266,7 +266,7 @@ liberation_maillon(struct_processus *s_e ================================================================================ Routine d'allocation d'une structure *s_objet ================================================================================ - Entrées : structure sur l'état du processus et objet à afficher + Entrées : structure sur l'état du processus et objet à allouer -------------------------------------------------------------------------------- Sorties : chaine de caractères -------------------------------------------------------------------------------- @@ -279,8 +279,20 @@ allocation(struct_processus *s_etat_proc { struct_objet *s_objet; + if (pthread_mutex_lock(&((*s_etat_processus).mutex_allocation)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(NULL); + } + if ((*s_etat_processus).pile_objets == NULL) { + if (pthread_mutex_unlock(&((*s_etat_processus).mutex_allocation)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(NULL); + } + // Il n'existe aucune structure struct_objet disponible dans le cache. if ((s_objet = malloc(sizeof(struct_objet))) == NULL) @@ -299,6 +311,12 @@ allocation(struct_processus *s_etat_proc (*s_etat_processus).taille_pile_objets--; (*s_objet).nombre_occurrences = 1; + + if (pthread_mutex_unlock(&((*s_etat_processus).mutex_allocation)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return(NULL); + } } (*s_objet).type = type; @@ -403,7 +421,10 @@ allocation(struct_processus *s_etat_proc } } + (*((struct_fonction *) (*s_objet).objet)).fonction = NULL; (*((struct_fonction *) (*s_objet).objet)).prediction_saut = NULL; + (*((struct_fonction *) (*s_objet).objet)).prediction_execution + = d_faux; break; } @@ -874,12 +895,21 @@ liberation(struct_processus *s_etat_proc { if (decrementation_atomique(s_objet) > 0) { + BUG((*(*((struct_fichier *) (*s_objet).objet)).format) + .nombre_occurrences <= 1, + pthread_mutex_unlock(&((*s_objet).mutex)), + printf("(*(*((struct_fichier *) (*s_objet).objet))" + ".format).nombre_occurrences=%ld\n", + (*(*((struct_fichier *) (*s_objet).objet)).format) + .nombre_occurrences)); + + liberation(s_etat_processus, + (*((struct_fichier *) (*s_objet).objet)).format); return; } liberation(s_etat_processus, (*((struct_fichier *) (*s_objet).objet)).format); - free((unsigned char *) (*((struct_fichier *) (*s_objet).objet)).nom); free((struct_fichier *) ((*s_objet).objet)); @@ -1092,7 +1122,6 @@ liberation(struct_processus *s_etat_proc return; } - free(s_objet); break; } @@ -1109,7 +1138,8 @@ liberation(struct_processus *s_etat_proc .nombre_references--; BUG((*(*((struct_processus_fils *) (*s_objet).objet)).thread) - .nombre_references < 0, printf("(*(*((struct_processus_fils" + .nombre_references < 0, uprintf( + "(*(*((struct_processus_fils" " *) (*s_objet).objet)).thread).nombre_references = %d\n", (int) (*(*((struct_processus_fils *) (*s_objet).objet)) .thread).nombre_references)); @@ -1136,10 +1166,14 @@ liberation(struct_processus *s_etat_proc pthread_mutex_destroy(&((*(*((struct_processus_fils *) (*s_objet).objet)).thread).mutex)); free((*((struct_processus_fils *) (*s_objet).objet)).thread); + } if (decrementation_atomique(s_objet) > 0) { + BUG(drapeau == d_vrai, uprintf("(*(*((struct_processus_fils" + " *) (*s_objet).objet)).thread).nombre_references " + "= 0 with nombre_occurrences > 0\n")); return; } @@ -1205,11 +1239,22 @@ liberation(struct_processus *s_etat_proc { if (decrementation_atomique(s_objet) > 0) { + BUG((*(*((struct_socket *) (*s_objet).objet)).format) + .nombre_occurrences <= 1, + pthread_mutex_unlock(&((*s_objet).mutex)), + printf("(*(*((struct_socket *) (*s_objet).objet))" + ".format).nombre_occurrences=%ld\n", + (*(*((struct_socket *) (*s_objet).objet)).format) + .nombre_occurrences)); + + liberation(s_etat_processus, (*((struct_socket *) + (*s_objet).objet)).format); return; } liberation(s_etat_processus, (*((struct_socket *) (*s_objet).objet)).format); + free((unsigned char *) (*((struct_socket *) (*s_objet).objet)) .adresse); free((unsigned char *) (*((struct_socket *) (*s_objet).objet)) @@ -1393,30 +1438,36 @@ liberation(struct_processus *s_etat_proc return; } - if (s_etat_processus != NULL) + if (pthread_mutex_lock(&((*s_etat_processus).mutex_allocation)) != 0) { - if ((*s_etat_processus).taille_pile_objets < TAILLE_CACHE) - { - (*s_objet).objet = (*s_etat_processus).pile_objets; - (*s_etat_processus).pile_objets = s_objet; - (*s_etat_processus).taille_pile_objets++; - } - else - { - if (pthread_mutex_destroy(&((*s_objet).mutex)) != 0) - { - (*s_etat_processus).erreur_systeme = d_es_processus; - return; - } + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } - free(s_objet); - } + if ((*s_etat_processus).taille_pile_objets < TAILLE_CACHE) + { + (*s_objet).objet = (*s_etat_processus).pile_objets; + (*s_etat_processus).pile_objets = s_objet; + (*s_etat_processus).taille_pile_objets++; } else { + if (pthread_mutex_destroy(&((*s_objet).mutex)) != 0) + { + pthread_mutex_unlock(&((*s_etat_processus).mutex_allocation)); + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + free(s_objet); } + if (pthread_mutex_unlock(&((*s_etat_processus).mutex_allocation)) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + return; } @@ -1746,6 +1797,14 @@ copie_objet(struct_processus *s_etat_pro if (type == 'P') { incrementation_atomique(s_objet); + + if (((*((struct_fichier *) ((*s_objet).objet))).format = + copie_objet(s_etat_processus, (*((struct_fichier *) + ((*s_objet).objet))).format, 'P')) == NULL) + { + return(NULL); + } + return(s_objet); } @@ -2236,6 +2295,7 @@ copie_objet(struct_processus *s_etat_pro (*((struct_processus_fils *) (*s_nouvel_objet).objet)) = (*((struct_processus_fils *) (*s_objet).objet)); + break; } @@ -2262,6 +2322,15 @@ copie_objet(struct_processus *s_etat_pro if (type == 'P') { incrementation_atomique(s_objet); + + if (((*((struct_socket *) ((*s_objet).objet))) + .format = copie_objet(s_etat_processus, + (*((struct_socket *) ((*s_objet).objet))).format, 'P')) + == NULL) + { + return(NULL); + } + return(s_objet); } @@ -2718,7 +2787,16 @@ copie_etat_processus(struct_processus *s * n'ont aucune raison de changer. */ +# ifndef SEMAPHORES_NOMMES sem_init(&((*s_nouvel_etat_processus).semaphore_fork), 0, 0); +# else + if (((*s_nouvel_etat_processus).semaphore_fork = sem_init2(0, sem_fork)) + == SEM_FAILED) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(NULL); + } +# endif (*s_nouvel_etat_processus).var_volatile_processus_pere = 0; (*s_nouvel_etat_processus).fichiers_graphiques = NULL; @@ -2730,6 +2808,7 @@ copie_etat_processus(struct_processus *s (*s_nouvel_etat_processus).expression_courante = NULL; (*s_nouvel_etat_processus).objet_courant = NULL; (*s_nouvel_etat_processus).processus_detache = d_faux; + (*s_nouvel_etat_processus).evaluation_forcee = 'N'; (*s_nouvel_etat_processus).nombre_objets_envoyes_non_lus = 0; (*s_nouvel_etat_processus).nombre_objets_injectes = 0; @@ -2749,6 +2828,10 @@ copie_etat_processus(struct_processus *s (*s_nouvel_etat_processus).nombre_interruptions_en_queue = 0; (*s_nouvel_etat_processus).nombre_interruptions_non_affectees = 0; + (*s_nouvel_etat_processus).at_exit = NULL; + (*s_nouvel_etat_processus).at_poke = NULL; + (*s_nouvel_etat_processus).traitement_at_poke = 'N'; + for(i = 0; i < d_NOMBRE_INTERRUPTIONS; i++) { (*s_nouvel_etat_processus).corps_interruptions[i] = NULL; @@ -2759,10 +2842,17 @@ copie_etat_processus(struct_processus *s if ((*s_nouvel_etat_processus).generateur_aleatoire != NULL) { - (*s_nouvel_etat_processus).generateur_aleatoire = NULL; - } + if (((*s_nouvel_etat_processus).generateur_aleatoire = + gsl_rng_clone((*s_etat_processus).generateur_aleatoire)) + == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(NULL); + } - (*s_nouvel_etat_processus).type_generateur_aleatoire = NULL; + gsl_rng_set((*s_nouvel_etat_processus).generateur_aleatoire, + gsl_rng_get((*s_etat_processus).generateur_aleatoire)); + } // Copie de la localisation @@ -3028,6 +3118,8 @@ copie_etat_processus(struct_processus *s (*s_etat_processus).s_liste_variables[i].niveau; (*s_nouvel_etat_processus).s_liste_variables[i].variable_statique = (*s_etat_processus).s_liste_variables[i].variable_statique; + (*s_nouvel_etat_processus).s_liste_variables[i].variable_partagee = + (*s_etat_processus).s_liste_variables[i].variable_partagee; (*s_nouvel_etat_processus).s_liste_variables[i].variable_verrouillee = (*s_etat_processus).s_liste_variables[i].variable_verrouillee; @@ -3482,6 +3574,12 @@ copie_etat_processus(struct_processus *s pthread_mutex_init(&((*s_nouvel_etat_processus).mutex), &attributs_mutex); pthread_mutexattr_destroy(&attributs_mutex); + pthread_mutexattr_init(&attributs_mutex); + pthread_mutexattr_settype(&attributs_mutex, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&((*s_nouvel_etat_processus).mutex_allocation), + &attributs_mutex); + pthread_mutexattr_destroy(&attributs_mutex); + if (pthread_mutex_unlock(&((*s_etat_processus).mutex)) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; @@ -3493,4 +3591,436 @@ copie_etat_processus(struct_processus *s #undef return } + +/* +================================================================================ + Routines de debug +================================================================================ + entrées : +-------------------------------------------------------------------------------- + sorties : +-------------------------------------------------------------------------------- + effets de bord : néant +================================================================================ +*/ + +#ifdef DEBUG_MEMOIRE + +#undef malloc +#undef realloc +#undef free +#undef fork + +#ifdef return +# undef return +#endif + +#ifdef __BACKTRACE +#define PROFONDEUR_PILE 64 +#define return(a) { if (a == NULL) \ + { BACKTRACE(PROFONDEUR_PILE); \ + fprintf(stderr, ">>> MEDITATION %d\n", __LINE__); } \ + return(a); } while(0) +#endif + +#undef fprintf +#define check(a, b) ((strcmp(#a, fonction) == 0) && (ligne == b)) +#undef CORE_DUMP + +typedef struct memoire +{ + void *pointeur; + unsigned char *fonction; + unsigned char *argument; + unsigned long ligne; + size_t taille; + unsigned long long ordre; +# ifdef __BACKTRACE + void *pile[PROFONDEUR_PILE]; + int profondeur; +# endif + struct memoire *suivant; +} struct_memoire; + +static struct_memoire *debug = NULL; +static unsigned long long ordre = 0; +static pthread_mutex_t mutex_allocation; + +void +debug_memoire_initialisation() +{ + pthread_mutexattr_t attributs_mutex; + + pthread_mutexattr_init(&attributs_mutex); + pthread_mutexattr_settype(&attributs_mutex, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mutex_allocation, &attributs_mutex); + pthread_mutexattr_destroy(&attributs_mutex); + + return; +} + +void * +debug_memoire_ajout(size_t taille, const unsigned char *fonction, + unsigned long ligne, const unsigned char *argument) +{ + struct_memoire *ancienne_base; + + void *pointeur; + + pthread_mutex_lock(&mutex_allocation); + + ancienne_base = debug; + + if ((debug = malloc(sizeof(struct_memoire))) == NULL) + { + pthread_mutex_unlock(&mutex_allocation); + return(NULL); + } + + if (((*debug).pointeur = malloc(taille)) == NULL) + { + pthread_mutex_unlock(&mutex_allocation); + return(NULL); + } + + (*debug).suivant = ancienne_base; + (*debug).ligne = ligne; + (*debug).taille = taille; + (*debug).ordre = ordre; + + pointeur = (*debug).pointeur; + +# ifdef __BACKTRACE + (*debug).profondeur = backtrace((*debug).pile, PROFONDEUR_PILE); +# endif + + if (((*debug).fonction = malloc((strlen(fonction) + 1) * + sizeof(unsigned char))) == NULL) + { + pthread_mutex_unlock(&mutex_allocation); + return(NULL); + } + + if (((*debug).argument = malloc((strlen(argument) + 1) * + sizeof(unsigned char))) == NULL) + { + pthread_mutex_unlock(&mutex_allocation); + return(NULL); + } + + strcpy((*debug).fonction, fonction); + strcpy((*debug).argument, argument); + + memset((*debug).pointeur, 0, (*debug).taille); + + pthread_mutex_unlock(&mutex_allocation); + ordre++; + + return(pointeur); +} + +void * +debug_memoire_modification(void *pointeur, size_t taille, + const unsigned char *fonction, unsigned long ligne, + const unsigned char *argument) +{ + struct_memoire *element_courant; + + if (pointeur != NULL) + { + if (taille == 0) + { + // Revient à free(). Il n'y a pas de parenthèses car on ne veut + // pas utiliser la macro return(). + + debug_memoire_retrait(pointeur); + return NULL ; + } + else + { + // Réallocation réelle + + pthread_mutex_lock(&mutex_allocation); + + element_courant = debug; + + while(element_courant != NULL) + { + if ((*element_courant).pointeur == pointeur) + { + break; + } + + element_courant = (*element_courant).suivant; + } + + if (element_courant == NULL) + { + pthread_mutex_unlock(&mutex_allocation); + + uprintf("[%d-%llu] ILLEGAL POINTER (realloc)\n", + getpid(), (unsigned long long) pthread_self()); +# ifdef __BACKTRACE + BACKTRACE(PROFONDEUR_PILE); +# endif + + return(realloc(pointeur, taille)); + } + else + { + if (((*element_courant).pointeur = realloc(pointeur, taille)) + == NULL) + { + pthread_mutex_unlock(&mutex_allocation); + return(NULL); + } + + (*element_courant).ligne = ligne; + (*element_courant).taille = taille; + free((*element_courant).fonction); + free((*element_courant).argument); + + if (((*element_courant).fonction = malloc((strlen(fonction) + + 1) * sizeof(unsigned char))) == NULL) + { + pthread_mutex_unlock(&mutex_allocation); + return(NULL); + } + + if (((*element_courant).argument = malloc((strlen(argument) + + 1) * sizeof(unsigned char))) == NULL) + { + pthread_mutex_unlock(&mutex_allocation); + return(NULL); + } + + strcpy((*element_courant).fonction, fonction); + strcpy((*element_courant).argument, argument); + + pthread_mutex_unlock(&mutex_allocation); + + return((*element_courant).pointeur); + } + } + } + else + { + // Revient à malloc() + pointeur = debug_memoire_ajout(taille, fonction, ligne, argument); + return(pointeur); + } +} + +void +debug_memoire_retrait(void *pointeur) +{ + struct_memoire *element_courant; + struct_memoire *element_precedent; + + pthread_mutex_lock(&mutex_allocation); + + element_courant = debug; + element_precedent = NULL; + + while(element_courant != NULL) + { + if ((*element_courant).pointeur == pointeur) + { + if (element_precedent == NULL) + { + debug = (*debug).suivant; + } + else + { + (*element_precedent).suivant = (*element_courant).suivant; + } + + if (pointeur != NULL) + { + memset(pointeur, 0, (*element_courant).taille); + } + + free((*element_courant).fonction); + free((*element_courant).argument); + free(element_courant); + + break; + } + + element_precedent = element_courant; + element_courant = (*element_courant).suivant; + } + + pthread_mutex_unlock(&mutex_allocation); + + if (element_courant == NULL) + { + uprintf("[%d-%llu] ILLEGAL POINTER (free)\n", + getpid(), (unsigned long long) pthread_self()); +# ifdef __BACKTRACE + BACKTRACE(PROFONDEUR_PILE); +# endif + } + + free(pointeur); + return; +} + +void +debug_memoire_verification() +{ +# ifdef __BACKTRACE + char **appels; + + int j; +# endif + + integer8 i; + + struct_memoire *element_courant; + struct_memoire *element_suivant; + + fprintf(stderr, "[%d-%llu] LIST OF MEMORY LEAKS\n", + getpid(), (unsigned long long) pthread_self()); + + pthread_mutex_lock(&mutex_allocation); + + element_courant = debug; + i = 1; + + while(element_courant != NULL) + { + fprintf(stderr, "[%d-%llu] MEDITATION %lld (%llu)\n", getpid(), + (unsigned long long) pthread_self(), i, + (*element_courant).ordre); + fprintf(stderr, "[%d-%llu] P: %p, F: %s(), L: %lu, S: %d\n", + getpid(), (unsigned long long) pthread_self(), + (*element_courant).pointeur, + (*element_courant).fonction, (*element_courant).ligne, + (int) (*element_courant).taille); + fprintf(stderr, "[%d-%llu] A: %s\n", getpid(), + (unsigned long long) pthread_self(), + (*element_courant).argument); + + if (strstr((*element_courant).argument, "sizeof(unsigned char)") + != NULL) + { + fprintf(stderr, "[%d-%llu] ", getpid(), + (unsigned long long) pthread_self()); + fprintf(stderr, "O: %s\n", (unsigned char *) + (*element_courant).pointeur); + } + else if (strcmp((*element_courant).argument, "sizeof(struct_objet)") + == 0) + { + fprintf(stderr, "[%d-%llu] ", getpid(), + (unsigned long long) pthread_self()); + fprintf(stderr, "O: %d\n", (*((struct_objet *) + (*element_courant).pointeur)).type); + } + else if (strcmp((*element_courant).argument, + "sizeof(struct_liste_chainee)") == 0) + { + fprintf(stderr, "[%d-%llu] ", getpid(), + (unsigned long long) pthread_self()); + fprintf(stderr, "O: data=%p next=%p\n", (*((struct_liste_chainee *) + (*element_courant).pointeur)).donnee, + (*((struct_liste_chainee *) (*element_courant).pointeur)) + .suivant); + } + +# ifdef __BACKTRACE + appels = backtrace_symbols((*element_courant).pile, + (*element_courant).profondeur); + + fprintf(stderr, "[%d-%llu] BACKTRACE\n", + getpid(), (unsigned long long) pthread_self()); + + if (appels != NULL) + { + for(j = 0; j < (*element_courant).profondeur; j++) + { + fprintf(stderr, "[%d-%llu] %s\n", getpid(), + (unsigned long long) pthread_self(), appels[j]); + } + + free(appels); + } +# endif + + fprintf(stderr, "\n"); + + i++; + + element_suivant = (*element_courant).suivant; + +# ifndef CORE_DUMP + free((*element_courant).fonction); + free((*element_courant).argument); + free(element_courant); +# endif + + element_courant = element_suivant; + } + + pthread_mutex_unlock(&mutex_allocation); + pthread_mutex_destroy(&mutex_allocation); + + fprintf(stderr, "[%d-%llu] END OF LIST\n", getpid(), + (unsigned long long) pthread_self()); + + return; +} + +pid_t +debug_fork() +{ + pid_t pid; + + pthread_mutex_lock(&mutex_allocation); + pid = fork(); + +# ifdef OS2 + if (pid == 0) + { + sem_init(&semaphore_liste_threads, 0, 1); + sem_init(&semaphore_gestionnaires_signaux, 0, 0); + sem_init(&semaphore_gestionnaires_signaux_atomique, 0, 1); + sem_init(&((*s_etat_processus).semaphore_fork), 0, 0); + } +# endif + + if (pid == 0) + { +# ifdef _BROKEN_SIGINFO + liberation_fifos_signaux(s_etat_processus); + creation_fifos_signaux(s_etat_processus); +# endif + + pthread_mutex_destroy(&mutex_allocation); + debug_memoire_initialisation(); + } + else + { + pthread_mutex_unlock(&mutex_allocation); + } + + // Pas de parenthèses pour ne pas remplacer return par sa macro. + return pid; +} + +void +analyse_post_mortem() +{ +# ifdef CORE_DUMP + BUG(debug != NULL, uprintf("[%d-%llu] CREATE CORE DUMP FILE FOR " + "POST MORTEM ANALYZE\n", getpid(), + (unsigned long long) pthread_self())); +# endif + + return; +} + +#endif + // vim: ts=4