--- rpl/src/interruptions.c 2012/05/16 14:45:25 1.95 +++ rpl/src/interruptions.c 2012/05/17 17:06:18 1.96 @@ -52,7 +52,6 @@ typedef struct liste_chainee_volatile volatile void *donnee; } struct_liste_chainee_volatile; - static volatile struct_liste_chainee_volatile *liste_threads = NULL; static volatile struct_liste_chainee_volatile *liste_threads_surveillance @@ -64,25 +63,107 @@ unsigned char *racine_segment; static pthread_mutex_t mutex_interruptions = PTHREAD_MUTEX_INITIALIZER; -void * +static void * thread_surveillance_signaux(void *argument) { - // Chaque kill() ou pthread_kill() incrémente le sémaphore. Lorsque le - // sémaphore est déverrouillé, on part dans un timeout. - // while(sem_wait()) - // { - // nanosleep(); - // if (errno == EINTR) - // { - // continue; - // } - // - // if (sem_trywait() != 0) - // { - // sem_post() - // kill() - // } - // } + // Cette fonction est lancée dans un thread créé par processus pour + // gérer le cas des appels système qui seraient bloqués lors de l'arrivée du + // signal SIGALRM. Les processus externes n'envoient plus un signal au + // processus ou au thread à signaler mais positionnent les informations + // nécessaires dans la queue des signaux et incrémentent le sémaphore. + // Le sémaphore est décrémenté lorsque le signal est effectivement traité. + + int nombre_signaux_envoyes; + + struct_processus *s_etat_processus; + + struct timespec attente; + + volatile struct_liste_chainee_volatile *l_element_courant; + + s_etat_processus = (struct_processus *) argument; + + for(;;) + { + attente.tv_sec = 0; + attente.tv_nsec = GRANULARITE_us * 1000; + +# ifndef SEMAPHORES_NOMMES + if (sem_wait(&(*s_queue_signaux).signalisation) == 0) +# else + if(sem_wait(semaphore_signalisation) == 0) +# endif + { + if ((*s_queue_signaux).requete_arret == d_vrai) + { + break; + } + + nombre_signaux_envoyes = 0; + + // Dans un premier temps, on verrouille la queue des signaux + // affectée au processus courant pour vérifier s'il y a quelque + // chose à traiter. + +# ifndef SEMAPHORES_NOMMES + sem_wait(&(*s_queue_signaux).semaphore); +# else + sem_wait(semaphore_queue_signaux); +# endif + + if ((*s_queue_signaux).pointeur_lecture != + (*s_queue_signaux).pointeur_ecriture) + { + nombre_signaux_envoyes++; + raise(SIGALRM); + } + +# ifndef SEMAPHORES_NOMMES + sem_post(&(*s_queue_signaux).semaphore); +# else + sem_post(semaphore_queue_signaux); +# endif + + // Dans un second temps, on balaye toutes les queues de signaux + // des threads du processus courant. + + pthread_mutex_lock(&mutex_liste_threads); + l_element_courant = liste_threads; + + while(l_element_courant != NULL) + { + if ((*((struct_thread *) (*l_element_courant).donnee)).pid + == getpid()) + { + if ((*(*((struct_thread *) (*l_element_courant).donnee)) + .s_etat_processus).pointeur_signal_ecriture != + (*(*((struct_thread *) (*l_element_courant).donnee)) + .s_etat_processus).pointeur_signal_lecture) + { + nombre_signaux_envoyes++; + pthread_kill((*((struct_thread *) (*l_element_courant) + .donnee)).tid, SIGALRM); + } + } + + l_element_courant = (*l_element_courant).suivant; + } + + pthread_mutex_unlock(&mutex_liste_threads); + + // Nanosleep + + if (nombre_signaux_envoyes > 0) + { + nanosleep(&attente, NULL); + } + } + else + { + (*s_etat_processus).erreur_systeme = d_es_processus; + } + } + pthread_exit(NULL); } @@ -2309,6 +2390,12 @@ scrutation_interruptions(struct_processu (*s_queue_signaux).pointeur_lecture = ((*s_queue_signaux).pointeur_lecture + 1) % LONGUEUR_QUEUE_SIGNAUX; + +# ifndef SEMAPHORES_NOMMES + sem_wait(&((*s_queue_signaux).signalisation)); +# else + sem_wait(semaphore_signalisation); +# endif } # ifndef SEMAPHORES_NOMMES @@ -2334,6 +2421,12 @@ scrutation_interruptions(struct_processu (*s_etat_processus).pointeur_signal_lecture = ((*s_etat_processus).pointeur_signal_lecture + 1) % LONGUEUR_QUEUE_SIGNAUX; + +# ifndef SEMAPHORES_NOMMES + sem_wait(&((*s_queue_signaux).signalisation)); +# else + sem_wait(semaphore_signalisation); +# endif } pthread_mutex_unlock(&mutex_interruptions); @@ -2726,6 +2819,8 @@ envoi_signal_contexte(struct_processus * void creation_queue_signaux(struct_processus *s_etat_processus) { + pthread_attr_t attributs; + unsigned char *nom; racine_segment = (*s_etat_processus).chemin_fichiers_temporaires; @@ -2774,6 +2869,7 @@ creation_queue_signaux(struct_processus # ifndef SEMAPHORES_NOMMES sem_init(&((*s_queue_signaux).semaphore), 1, 1); + sem_init(&((*s_queue_signaux).signalisation), 1, 0); # else if ((semaphore_queue_signaux = sem_init2(1, getpid(), SEM_QUEUE)) == SEM_FAILED) @@ -2781,10 +2877,18 @@ creation_queue_signaux(struct_processus (*s_etat_processus).erreur_systeme = d_es_processus; return; } + + if ((semaphore_signalisation = sem_init2(1, getpid(), + SEM_SIGNALISATION)) == SEM_FAILED) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } # endif (*s_queue_signaux).pointeur_lecture = 0; (*s_queue_signaux).pointeur_ecriture = 0; + (*s_queue_signaux).requete_arret = d_faux; if (msync(s_queue_signaux, sizeof(struct_queue_signaux), 0)) { @@ -2848,8 +2952,10 @@ creation_queue_signaux(struct_processus } sem_init(&((*s_queue_signaux).semaphore), 1, 1); + sem_init(&((*s_queue_signaux).signalisation), 1, 0); (*s_queue_signaux).pointeur_lecture = 0; (*s_queue_signaux).pointeur_ecriture = 0; + (*s_queue_signaux).requete_arret = d_faux; # else // OS/2 if ((nom = nom_segment(NULL, getpid())) == NULL) { @@ -2869,11 +2975,65 @@ creation_queue_signaux(struct_processus free(nom); sem_init(&((*s_queue_signaux).semaphore), 1, 1); + sem_init(&((*s_queue_signaux).signalisation), 1, 0); (*s_queue_signaux).pointeur_lecture = 0; (*s_queue_signaux).pointeur_ecriture = 0; + (*s_queue_signaux).requete_arret = d_faux; # endif # endif + // Lancement du thread de récupération des signaux. + + if (pthread_attr_init(&attributs) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + + if (pthread_attr_setdetachstate(&attributs, + PTHREAD_CREATE_JOINABLE) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + +# ifdef SCHED_OTHER + if (pthread_attr_setschedpolicy(&attributs, SCHED_OTHER) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } +# endif + +# ifdef PTHREAD_EXPLICIT_SCHED + if (pthread_attr_setinheritsched(&attributs, PTHREAD_EXPLICIT_SCHED) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } +# endif + +# ifdef PTHREAD_SCOPE_SYSTEM + if (pthread_attr_setscope(&attributs, PTHREAD_SCOPE_SYSTEM) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } +# endif + + if (pthread_attr_destroy(&attributs) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + + if (pthread_create(&((*s_queue_signaux).thread_signaux), &attributs, + thread_surveillance_signaux, s_etat_processus) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + return; } @@ -2894,6 +3054,18 @@ creation_queue_signaux(struct_processus void liberation_queue_signaux(struct_processus *s_etat_processus) { + // Incrémenter le sémaphore pour être sûr de le débloquer. + + (*s_queue_signaux).requete_arret = d_vrai; + +# ifndef SEMAPHORES_NOMMES + sem_post(&((*s_queue_signaux).signalisation)); +# else + sem_post(semaphore_signalisation); +# endif + + pthread_join((*s_queue_signaux).thread_signaux, NULL); + # ifdef IPCS_SYSV // SystemV # ifndef OS2 if (shmdt(s_queue_signaux) == -1) @@ -2906,8 +3078,10 @@ liberation_queue_signaux(struct_processu # else // POSIX # ifndef SEMAPHORES_NOMMES sem_close(&((*s_queue_signaux).semaphore)); + sem_close(&((*s_queue_signaux).signalisation)); # else sem_close(semaphore_queue_signaux); + sem_close(semaphore_signalisation); # endif if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0) @@ -2954,6 +3128,16 @@ destruction_queue_signaux(struct_process } unlink((*s_queue_signaux).semaphore.path); + free((*s_queue_signaux).semaphore.path); + + if (semctl((*s_queue_signaux).signalisation.sem, 0, IPC_RMID) == -1) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + + unlink((*s_queue_signaux).signalisation.path); + free((*s_queue_signaux).signalisation.path); if (shmdt(s_queue_signaux) == -1) { @@ -2980,6 +3164,9 @@ destruction_queue_signaux(struct_process sem_close(&((*s_queue_signaux).semaphore)); sem_destroy(&((*s_queue_signaux).semaphore)); + sem_close(&((*s_queue_signaux).signalisation)); + sem_destroy(&((*s_queue_signaux).signalisation)); + if (DosFreeMem(s_queue_signaux) != 0) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; @@ -2990,9 +3177,15 @@ destruction_queue_signaux(struct_process # ifndef SEMAPHORES_NOMMES sem_close(&((*s_queue_signaux).semaphore)); sem_destroy(&((*s_queue_signaux).semaphore)); + + sem_close(&((*s_queue_signaux).signalisation)); + sem_destroy(&((*s_queue_signaux).signalisation)); # else sem_close(semaphore_queue_signaux); sem_destroy2(semaphore_queue_signaux, getpid(), SEM_QUEUE); + + sem_close(semaphore_signalisation); + sem_destroy2(semaphore_signalisation, getpid(), SEM_SIGNALISATION); # endif if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)