Question

Je suis en train d'élaborer un programme à temps limite l'exécution d'une fonction. Dans le code ci-dessous j'ai une fonction nommée Inc qui fait beaucoup d'itérations (simulée par la boucle infinie). La première partie de chaque itération est assez longue, suivie d'une seconde partie qui devrait être assez rapide.

Je ne me dérange pas préempter l'exécution alors que dans la première partie du code, mais je voudrais éviter que l'alarme va hors tout en faisant une opération d'écriture sur la deuxième partie.

Ma première idée était de désactiver l'alarme avant d'entrer dans l'économie « zone sûre » le temps restant. Puis, après la sortie, je mettrais l'alarme avec le gain de temps. Je ne sais pas comment mettre en œuvre. Quelqu'un pourrait-il me aider? Des méthodes alternatives sont également les bienvenus.

#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

pthread_t thread;
FILE *fout;

void *Inc(void *param){

    int i;
    long long int x = 0;

    fout = fopen("file.txt", "w");

    /* Large number of iterations */
    while(1){

        int k = 0;
        for(i=0; i<5000000; i++)
            k += (rand())%3;
        x += k;

        printf("%lld\n", x);
        /* Enter Safe Region */
        fprintf(fout, "%lld\n", x);
        /* Exit Safe Region */
    }   
}

void Finish(int param){
    pthread_cancel(thread);
    fclose(fout);
}

main (){

    pthread_attr_t attr;
    void *status;

    signal(SIGALRM, Finish);
    alarm(10);

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    pthread_create(&thread, &attr, Inc, NULL);
    pthread_attr_destroy(&attr);
    pthread_join(thread, &status);

    printf("Program Finished\n");
}
Était-ce utile?

La solution

La chose évidente est de prendre un verrou avant d'appeler pthread_cancel, et de tenir le même verrou sur votre « zone sûre ».

Malheureusement, vous ne pouvez pas attendre sur un mutex ou un sémaphore dans un gestionnaire de signaux. Mais les signaux d'alarme ne sont pas la seule façon de faire quelque chose au bout de 10 secondes - vous pourriez plutôt avoir votre Princ de fil pour dormir pendant 10 secondes, puis se réveiller, prendre le verrou, annuler le thread de travail puis rejoindre

Bien sûr, cela signifierait que le fil conducteur dormira 10 secondes, même si la fin du thread de travail au bout de 5 secondes. Ainsi, au lieu de dormir, ont le thread principal faire 10 secondes chronométré attente sur un sémaphores, que les messages de fil des travailleurs quand il se termine.

Comme un sommeil, une attente chronométrée peut terminer prématurément en raison d'un signal, alors assurez-vous de retenter l'attente chronométrée sur EINTR. Vos affaires importantes sont EINTR (attendre encore), le succès (rejoindre le thread de travail - pas besoin d'annuler car il a affiché le sémaphores), ETIMEDOUT (prendre le verrou, annuler, rejoindre) et si vous le souhaitez, d'autres erreurs. Il n'y a pas d'autres erreurs répertoriées pour sem_timedwait qui devraient vous affecter, cependant.

Une autre idée est de bloquer SIGALRM dans votre « zone sûre », ce qui serait plus simple, sauf que (a) Je ne me souviens jamais comment faire en toute sécurité E / S avec des signaux désactivé, et (b) votre thread de travail pourrait probablement en cours d'exécution « en même temps » avec le gestionnaire de signaux (soit réellement simultanée ou en apparence en raison de pré-emption), ce qui signifie que le signal pourrait être prise, alors vos signaux adaptés aux personnes handicapées des travailleurs et pénètre dans la zone critique, le gestionnaire de signal annule. Si personne ne répond, qui peut réellement se souvenir des détails, voici quelques

scroll top