#define _POSIX_C_SOURCE 200112L #include #include #include #include #include #include #include #include "err.h" typedef struct message { char *contenu; int nb_repetitions; int descripteur; } message; int retour; pthread_mutex_t verrou_desc; void *f(void *arg) { message *m; m=(message *)arg; printf("Recu l'argument \"%s\" a repeter %d fois\n", m->contenu, m->nb_repetitions); int taille = strlen(m->contenu); for (int j = 0; j < m->nb_repetitions; j++) { pthread_mutex_lock(&verrou_desc); if (write(m->descripteur, m->contenu, taille) < 0) FATAL("write"); pthread_mutex_unlock(&verrou_desc); } retour += 10; // pour illustrer le retour. pthread_exit(&retour); // retour doit être statique/globale. return NULL; // Non atteint si pthread_exit réussit. } void usage(char *s) { fprintf(stderr, "Usage: %s \n\n", s); fprintf(stderr, "Lance 2 threads, le premier ecrit nb_repetitions de la chaine 1 dans le fichier argument.\n" "Le 2eme ecrit nb_repetitions de la chaine 2 dans le fichier, via le meme descripteur.\n" "Le thread main attend les deux autres, dans l'ordre de leur creation.\n\n" "Met en evidence qu'un processus peut etre interrompu entre l'ecriture et le deplacement de la tete.\n"); exit(EXIT_FAILURE); } int main(int argc, char **argv) { pthread_t id1, id2; if (argc != 5) usage(argv[0]); int descr = open(argv[4], O_WRONLY | O_CREAT | O_TRUNC /* | O_APPEND */ , S_IRUSR|S_IWUSR); if (descr == -1) FATAL("open"); // Initialisation des verrous if (pthread_mutex_init(&verrou_desc, NULL) < 0) FATAL("pthread_mutex_init"); // Fabrication de l'argument à passer au premier thread. message m1; m1.contenu = malloc(strlen(argv[1])+1); strncpy(m1.contenu, argv[1], strlen(argv[1])); m1.nb_repetitions = atoi(argv[3]); m1.descripteur = descr; // Lancement du premier thread. if (pthread_create(&id1, NULL, f, &m1) < 0) FATAL("pthread_create"); // Fabrication de l'argument à passer au second thread. message m2; m2.contenu = malloc(strlen(argv[2])+1); strncpy(m2.contenu, argv[2], strlen(argv[2])); m2.nb_repetitions = atoi(argv[3]); m2.descripteur = descr; // Lancement du second thread. if (pthread_create(&id2, NULL, f, &m2) < 0) FATAL("pthread_create"); // Attente de terminaison du thread id1. void *p; pthread_join(id1, &p); printf("Thread %d termine avec retour %d\n", (int)id1, **(int **)&p); // Attente de terminaison du thread id2. pthread_join(id1, &p); printf("Thread %d termine avec retour %d\n", (int)id2, **(int **)&p); // Comme les threads ne sont pas synchronisés pour l'accès à la // variable retour, on peut avoir ici comme valeurs (10,10), ou // (10,20), ou (20,20). Comment obtenir (10,20) ? return EXIT_SUCCESS; }