IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

Exclusion total de deux pthread [et non de partie critique]


Sujet :

Réseau C

  1. #1
    Membre régulier Avatar de Thor Tillas
    Inscrit en
    Octobre 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 113
    Points : 90
    Points
    90
    Par défaut Exclusion total de deux pthread [et non de partie critique]
    bonjour tout le monde,

    Alors voilà. le but de mon programme est de simuler un monothread. Bien sur comme ce programme doit poller le réseau, il faut qu'une méthode s'active toutes les x secondes pour vérirfier si par hasard il n'y aurait pas de nouveau message.

    Sur les machines de distribution, je sais qu'il existe une sorte d'interruption que je peux rediriger vers une méthode. Cette interruption est appelé régulièrement. Je n'ai donc pas besoin de m'occuper de créer ce mécanisme.

    Sur mes machine de test, j'ai un linux tout à fait normal. J'utilise un pthread pour mon programme et un autre pour simuler l'interruption.

    Mon problème est le suivant.

    Si je veux simuler réellement ma machine de distribution il faut que je puisse m'assurer que lorsque mon thread interruption est réveiller, l'autre thread ne puisse pas revenir avant la fin du thread interruption.

    En gros je veux que mon thread interruption empêche le thread de mon programme de reprendre la main tant qu'il n'a pas fini.

    Bien sur j'ai tout de suite pensé au mutex. Mais comme mon programme peut être interrompu n'importe quand, il faudrait que je teste à chaque ligne si la variable mutex est libre. Ce qui est bien sur impensable.

    Ayant étudier quelques temps les pth (portable thread coté utilisateur) je me suis dit qu'une fonction suspend devait surement exister du coté des pthread. Que nenni me dit t on sur google...

    Je sais plus trop ou chercher...
    Est ce qu'il existe un moyen de faire de l'exclusion non pas de partie de code, mais de thread ou de transformer un thread non préemptif en préemptif...

    Si vous avez des idées, suggestions... Je les acceptes toutes... même et surtout si c'est pour me dire que c'est impossible... ca m'évitera de me casser la tête trop longtemps


    Merci d'avance
    Au travail, il y a deux sortes de personnes. Ceux qui ont un pistolet chargé, et ceux qui creusent. Moi je creuse...

  2. #2
    Membre régulier Avatar de Thor Tillas
    Inscrit en
    Octobre 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 113
    Points : 90
    Points
    90
    Par défaut
    Je viens de trouver une nouvelle info et donc ca me mène à une question :

    - Qu'est ce qu'une priotrité pthread ?

    Si je défini une priorité super haute pour mon interruption est ce que par hasard ca pourrait correspondre à ce que je recherche ?
    Ou ca ne fera que déplacer le problème puisque seul le thread d'interruption sera utiliser... (a savoir que je fais un sleep dans le thread interruption j'imagine que tant qu'il sleep l'autre à le droit de faire quelque chose)
    Au travail, il y a deux sortes de personnes. Ceux qui ont un pistolet chargé, et ceux qui creusent. Moi je creuse...

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    136
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2004
    Messages : 136
    Points : 133
    Points
    133
    Par défaut
    lu

    lorsque le thread interruption démarre, il peut envoyer un signal (pthread_kill) à l'autre thread pour lui demander de s'arrêter, et un autre lorsqu'il termine pour lui demander de continuer.

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Thor Tillas
    Est ce qu'il existe un moyen de faire de l'exclusion non pas de partie de code, mais de thread ou de transformer un thread non préemptif en préemptif...
    C'est une question de système. Les pthreads sous Windows XP sont préemptifs. Sous Linux, j'ai cru comprendre que ça dépendait du noyau (2.4, 2.6...) et de certains réglages...
    Pas de Wi-Fi à la maison : CPL

  5. #5
    Membre confirmé Avatar de Tchetch
    Inscrit en
    Mars 2002
    Messages
    401
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Mars 2002
    Messages : 401
    Points : 477
    Points
    477
    Par défaut
    Je pense que tu devrais faire ça avec des signaux et deux processus. Un processus qui régulièrement lève un signal, par exemple SIGUSR1, pour simuler l'interruption générée sur ta machine de production et l'autre processus correspond on programme que tu veux tester. Ensuite tu n'aurais plus qu'à modifier ton programme pour qu'il utilise l'interruption de ta machine de production au lieu du signal.
    Mon wiki (on y parle Debian principalement) : http://www.tchetch.net/

  6. #6
    Membre régulier Avatar de Thor Tillas
    Inscrit en
    Octobre 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 113
    Points : 90
    Points
    90
    Par défaut
    Citation Envoyé par sympho
    lu

    lorsque le thread interruption démarre, il peut envoyer un signal (pthread_kill) à l'autre thread pour lui demander de s'arrêter, et un autre lorsqu'il termine pour lui demander de continuer.
    euh... le pthread_kill ne détruit pas totalement le pthread ? je pensais que cette méthode était utilisé pour mettre fin violemment à un pthread...


    @Tchetch : ok je vais voir dans cette direction. j'y avais pas pensé. Ca pourrait répondre à mon problème en fait.

    @Emmanuel : Merci pour la précision, je vais voir la version de mon noyau et je ferais une recherche sur google pour savoir. (si je trouve quelque chose je le poste)

    Merci pour vos réponses.

    Une question reste en suspend... Comment sont utilisé les priorité de pthread ?

    Si j'ai un pthread avec une priorité plus haute, est ce qu'il l'execute jusqu'à ce qu'il soit fini ou il prend quand meme le temps de s'occuper des priorités plus basse ?
    Au travail, il y a deux sortes de personnes. Ceux qui ont un pistolet chargé, et ceux qui creusent. Moi je creuse...

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ça dépend.
    Sous Windows, c'est la première solution au début, mais tout thread qui n'a pas été "servi" depuis plus de trois secondes est placé en priorité semi-maximale pour deux unités de temps, avant de retomber à sa priorité normale, pour éviter les famines...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre régulier Avatar de Thor Tillas
    Inscrit en
    Octobre 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 113
    Points : 90
    Points
    90
    Par défaut
    ok alors pour ce que j'ai trouvé sur pthread_kill ca me parait correspondre à ce que je recherche.

    Mon seul soucis c'est comment je peux traiter le signal que je recois. L'envoyer est assez simple puisque je fais pthread_kill(progID,SIGUSR1) où progID est le pid de mon thread "programme".

    Par contre du coté du thread "programme" comment je fais pour dire, lorsque tu recois ce signal, tu fais ca. lorsque tu recois encore une fois ton signal tu fais ca.


    Je recherche en parrallèle sur google donc il se peut que je trouve la réponse tout seul mais si quelqu'un l'a sous la main, ca ira plus vite


    [EDIT] ca m'a pris moins de temps que prévu... donc euh.. signal() permet de définir un handler...
    Donc si je le défini au début de mon thread, chaque fois qu'il aura un signal du type voulu, il va appeler le handler.

    J'imagine donc que cette méthode n'est pas un wait sur un signal, mais une inscription à observateur d'evenement... Suis je sur la bonne voie ou je me trompe du tout au tout...
    Au travail, il y a deux sortes de personnes. Ceux qui ont un pistolet chargé, et ceux qui creusent. Moi je creuse...

  9. #9
    Membre confirmé Avatar de Tchetch
    Inscrit en
    Mars 2002
    Messages
    401
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Mars 2002
    Messages : 401
    Points : 477
    Points
    477
    Par défaut
    Oui, tu peux utiliser signal comme tu le penses (donc tu passes dans une fonction quand tu reçois le signal défini) mais pour les processus parce que :
    Citation Envoyé par man signal
    NOTES
    Les effets de cet appel dans un processus multi-fils (Ndt : thread)
    sont indéterminés.
    Mon wiki (on y parle Debian principalement) : http://www.tchetch.net/

  10. #10
    Membre régulier Avatar de Thor Tillas
    Inscrit en
    Octobre 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 113
    Points : 90
    Points
    90
    Par défaut
    Mais alors dans ce cas à quoi sert le pthread_kill ?

    Si le fait d'utiliser les signaux n'est pas permis avec les threads qu'elle est l'intérêt de fournir une fonction qui permet de les utiliser.

    Je sais pas si ca a un rapport, mais sous linux je crois que chaque thread est un processus. Est ce que ca peut répondre au problème du signal ?

    [EDIT] voici ce que j'ai trouvé sur un site dans pour l'explication du signal: (http://www.up-comp.com/french/ressou...nal/index.html)

    Avertissement

    Seul le premier thread du processus est dérouté.
    comme j'ai un processus par thread ou un thread par processus c'est égal, signal devrait tout de meme fonctionner... Ou je me trompe
    Au travail, il y a deux sortes de personnes. Ceux qui ont un pistolet chargé, et ceux qui creusent. Moi je creuse...

  11. #11
    Membre régulier Avatar de Thor Tillas
    Inscrit en
    Octobre 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 113
    Points : 90
    Points
    90
    Par défaut
    ok j'ai fait mes premier test... et ca compile.. c'est déjà un début.

    Bien entendu après ca foire... mon programme par en boucle.

    Donc j'ai penser à une méthode handler de ce genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    void paroc_broker::signalHandler(int signalType){
      printf("paroc_broker::signalHandler : a signal is raise\n");
      if(signalType == SIGUSR1){
        printf("paroc_broker::signalHandler : the signal is a SIGUSR1\n");
        sigset_t ens; int sig;
        sigemptyset (&ens); sigaddset (&ens,SIGUSR2);
        printf("paroc_broker::signalHandler : wait for the other signal\n");
        sigwait (&ens,&sig);
        printf("paroc_broker::signalHandler : end of wait\n");
      }
    }
    Mon thread fait un truc du genre (le code est assez grand et il fait appel à plein de méthode... donc si vous voulez vraiment je vous le met en entier...)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    void monThread(...){
      while(1){
        usleep(5000);
        pthread_kill(programID,SIGUSR1);
        ...
        //je fais ce que je dois faire (poller le réseau durant un temps limite, récup une requete... etc)
        ...
        pthread_kill(programID,SIGUSR2);
      }
    }
    Pour l'instant j'ai l'impression que le thread programme il arrive pas à prendre les deux signal. Il récupère le signal SIGUSR1, se met en mode attente et laisse donc le thread poll continuer. Ensuite le thread poll il fait le sigusr2 et refait un sigusr1 direct après. Ce qui oblige le thread prog à recommencer à attendre et il arrive plus à faire ce qu'il a à faire.

    Pourtant un usleep(5000) devrait lui donner pas mal de temps... je comprends pas trop pourquoi il se vautre.

    Aurais-je manqué quelque chose ?



    P.S bon puisque je suis là voici le code de la partie poll de réseau : Je sais pas trop si c'est compréhensible ca fait partie de mon projet de comprendre ce qui se passe dans ces méthodes pour pouvoir les modifier... et le type qui s'en occupait avant n'avait pas l'habitude de mettre des commentaires...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
     
    void paroc_broker::ReceiveThread(paroc_combox *server) // Receive request and put request in the FIFO
    {
     
      server->SetCallback(COMBOX_NEW, NewConnection, this);
      server->SetCallback(COMBOX_CLOSE, CloseConnection, this);
      while (isRunning)
        {
          usleep(5000);
          if(pthread_kill(programID, SIGUSR1)==-1) printf("paroc_broker::ReceiveThread : signal broked\n");
          pthread_yield();
          paroc_request req;
          req.data=NULL;
          try
            {
              printf("paroc_broker::ReceiveThread() : call ReceiveRequest()\n");
              if (!ReceiveRequest(server, req)) break;
              printf("paroc_borker::ReceiveThread() : ReceiveRequest done\n");
              if (!timeout){
                if (ParocCall(req))
                  {
                    if (req.data!=NULL) req.data->Destroy();
                    execCond.broadcast();
                    pthread_kill(programID, SIGUSR2); 
                    pthread_yield();
                    continue;
                  }
                if (isThreadless) {
     
                  mutexCond.lock();
                  if(mutexCount) printf("paroc_broker::ReceiveThread : Il y a une mutex en attente\n");
                  while (mutexCount)
                  {
                    mutexCond.wait();
                  }
                  mutexCond.unlock();
                  printf("paroc_broker::ReceiveThread : pas de mutex en attente\n");
                  RegisterThreadless(req);
                }
                else RegisterRequest(req);
              }
            }
    catch (...)
            {
              server->Close();
              if (req.data!=NULL) req.data->Destroy();
              execCond.broadcast();
              pthread_kill(programID, SIGUSR2);
              pthread_yield();
              break;
            }
          printf("paroc_broker::ReceiveThread() : will start another loop\n");
          pthread_kill(programID, SIGUSR2);
          pthread_yield();
        }
      server->Close();
    }
     
     
    bool paroc_broker::ReceiveRequest(paroc_combox *server, paroc_request &req)
    {
     
      while (isRunning)
        {
          int timer = 1;
          //cette méthode retourne un objet qui englobe une socket qui a recu 
          //un message
          paroc_connection *conn=server->Wait(timer);
          printf("paroc_broker::ReceiveRequest() : wait passed\n");
          //si on recoit un objet null et que le timer est arrivé à zéro, 
          //ben c'est qu'on a pas eu le temps de recevoir quelque chose
          if(conn == NULL && timer==0){
                  printf("paroc_broker::ReceiveRequest() : timeout\n");
                  timeout = true;
                  return true;
          }
          timeout=false;
          if (conn==NULL || !isRunning)
          {
            execCond.broadcast();
            return false;
          }
          paroc_buffer_factory *fact=conn->GetBufferFactory();
          req.data=fact->CreateBuffer();
          if (req.data->Recv(conn))
          {
            req.from=conn;
            const paroc_message_header &h=req.data->GetHeader();
            req.methodId[0]=h.GetClassID();
            req.methodId[1]=h.GetMethodID();
            if ( !((req.methodId[2]=h.GetSemantics()) & INVOKE_SYNC) ) server->SendAck(conn);
              return true;
          }
     
     
          req.data->Destroy();
        }
      return false;
    }
    Au travail, il y a deux sortes de personnes. Ceux qui ont un pistolet chargé, et ceux qui creusent. Moi je creuse...

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    136
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2004
    Messages : 136
    Points : 133
    Points
    133
    Par défaut
    salut,

    Citation Envoyé par Thor Tillas
    Pourtant un usleep(5000) devrait lui donner pas mal de temps...
    l'unité de l'argument de usleep c'est des microsecondes soit 10^-6
    usleep(5000) demande à ton thread d'attendre 5 milli secondes (pas un peu court ?). en fonction de la résolution du noyau du système sur lequel tu tournes, il n'est pas exclu que l'appel usleep retourne immédiatement, d'où la boucle.

  13. #13
    Membre régulier Avatar de Thor Tillas
    Inscrit en
    Octobre 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 113
    Points : 90
    Points
    90
    Par défaut
    ok je vais essayer avec sleep(1)

    [EDIT] j'avais aussi un poll(xxx,xxx, -1) dans le wait(int) évidemment que je ne veux pas que ca attendent à l'infini...


    Je vous tiens au courant de mes erreurs par edit de ce post pour éviter le flood
    Au travail, il y a deux sortes de personnes. Ceux qui ont un pistolet chargé, et ceux qui creusent. Moi je creuse...

  14. #14
    Membre régulier Avatar de Thor Tillas
    Inscrit en
    Octobre 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 113
    Points : 90
    Points
    90
    Par défaut
    Bon j'ai un problème.... que je ne sais pas trop comment résoudre.

    En gros.

    J'ai l'impression que le pthread network lève trop de signal SIGUSR1 et que finalement le thread program ne fait qu'attendre et ne bosse jamais. Dès qu'il sort du sigwait, il y retourne parce qu'il a recu un SIGUSR1.

    Je sais pas trop comment faire pour vérifier que ca ne parte pas en boucle.

    Voilà euh... comment dire... euh si vous avez une idée génial, ben euh... je vous remercie d'avance de prendre un peu de temps pour la déposer juste après...
    Au travail, il y a deux sortes de personnes. Ceux qui ont un pistolet chargé, et ceux qui creusent. Moi je creuse...

  15. #15
    Membre régulier Avatar de Thor Tillas
    Inscrit en
    Octobre 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 113
    Points : 90
    Points
    90
    Par défaut
    I am a génie

    ok je sors...

    bon voici la solution pour ceux qui se sont intéresser à mon problème et aussi pour ceux qui pourrait un jour retomber dessus...

    Donc en regardant de plus près les divers signaux possible à envoyer, j'en ai vu deux qui répondent parfaitement à mon problème (j'ai trouvé l'info ici : http://foireatout.no-ip.com/IRIS/TPLinux/Signaux.pdf):

    SIGCONT : reprise d'un processus arrêter
    SIGSTOP : arrête un processus (reprise avec SIGCONT)
    Mais comment ca s'utilise ces foutus signaux que je me suis dis... en fait c'est vraiment super simple.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    pthread_kill(<id du thread à stopper>,SIGSTOP);
    pthread_kill(<id du thread à faire repartir>, SIGCONT);
    voici un diagramme qui vous montre l'idée de mon prog :


    Voilà merci encore à tous ceux qui ont passé du temps à essayer de résoudre mes problèmes.... Merci...

    Et pis j'espère que cette solution pourra être utilisée par quelqu'un...
    Au travail, il y a deux sortes de personnes. Ceux qui ont un pistolet chargé, et ceux qui creusent. Moi je creuse...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] En ASP.NET, comment afficher un messagebox avec deux boutons OUI/NON?
    Par ronot dans le forum ASP.NET
    Réponses: 2
    Dernier message: 29/01/2013, 16h29
  2. deux boucles for non imbriquées
    Par ebenmous dans le forum Langage
    Réponses: 3
    Dernier message: 24/06/2011, 11h53
  3. charger deux images bitmap non visibles
    Par Madman dans le forum Visual Studio
    Réponses: 0
    Dernier message: 15/04/2010, 10h52
  4. SELECT classique + Total en 1 seule requête non-imbriquée
    Par thonglith dans le forum Requêtes
    Réponses: 3
    Dernier message: 22/07/2008, 17h55
  5. Réponses: 9
    Dernier message: 12/10/2006, 00h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo