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

Threads & Processus C++ Discussion :

Setjmp/longjmp en C++


Sujet :

Threads & Processus C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 17
    Par défaut Setjmp/longjmp en C++
    Bonjour a tous, je suis un etudiant en informatique.
    Actuellement je prends un cours sur les systèmes d'exploitation et nous avons un petit projet à rendre pour ce soir qui consiste à implémenter une librairie de threads "user-level".
    J'ai essayé longuement de comprendre le problème par moi meme mais j'avoue que je commence à perdre patience...

    Je ne veux pas trop rentrer dans les détails pour ne pas vous faire perdre de temps mais en gros ce qui me pose problème est l'utilisation des macros setjmp/longjmp en C++.
    Pour ceux qui ne connaissent pas, ces fonctions permettent de sauvegarder l'état du CPU (SP, FP, PC entre autres).

    Mon problème est dans l'utilisation de setjmp à l'intérieur du constructeur: en fait je passe à mon constructeur un pointeur vers une fonction f qui correspond à ce que doit éxécuter le "thread" quand il sera exécuté. Je sauvegarde l'adresse de cette fonction dans le pc à l'aide de setjmp ainsi que le sp et fp. La fonction avec du code asm est une black box pour raisons de compatibilité.

    Dans mon driver, je crée un objet auquel je passe une fonction de test qui imprime un string.
    Une fois mon object créé, j'appelle la fonction longjmp avec comme parametre le buffer qui a sauvegardé l'état du thread précédemment.
    Voici le code:

    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
     
    #ifndef _THREAD_H
    #define _THREAD_H
     
    #include <iostream>
    #include "uthreads.hh"
    #define JB_SP 4
    #define JB_PC 5
     
    enum State{
      READY,
      SUSPENDED,
      RUNNING
    };
     
     
     
    class Thread{
     
     private:
      int _id;
      int _prior;
      State _state;
     
     
      char _stack[STACK_SIZE];
     
     public:
     
      // Initializes the thread and sets up the buffers for use later.
      Thread(void (*thread_func)(void), int priority);
     
      //A translation required when using an address of a variable
      //Use this as a black box in your code.
      //unsigned int translate_address(unsigned int addr);
     
      int getId();
      jmp_buf _buffer;   
      void setPriority(int priority);
     
      int getPriority();
     
      void saveState();
     
      void loadState();
     
      void setState(State state);
     
      State getState();
     
    };
    #endif
    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
     
    #include "Thread.h"
    #include <cassert>
    #include <new>
    static unsigned int counter = 0;
     
    //A translation required when using an address of a variable
    //Use this as a black box in your code.
    static unsigned int translate_address(unsigned int addr)
    {
      unsigned int ret;
      asm volatile("xor    %%gs:0x18,%0\n"
    	       "rol    $0x9,%0\n"
    	       : "=g" (ret)
    	       : "0" (addr));
     
      return ret;
    }
     
    // Initializes the thread and sets up the buffers for use later.
    Thread::Thread(void (*thread_func)(void), int priority){
      _prior = priority;
      // This is the main thread.
      if (counter == 0) {
        _state = RUNNING;
      }
      else {
        _state = READY;
      }
      _id = counter;
      counter++;
      //_stack = NULL;
      // Sets the jbuf for execution at thread_func the next
      // time we'll call longjmp.
     
      unsigned int sp, pc;
      if (thread_func != NULL) {
        //_stack = new char[STACK_SIZE];
        sp = (unsigned int) _stack + STACK_SIZE - sizeof(int);
        // We want the  thread to start at threadfunc.
        pc = (unsigned int) thread_func;
      }
     
      setjmp(_buffer);
      if (thread_func != NULL) {
        (_buffer->__jmpbuf)[JB_SP] = translate_address(sp);
        (_buffer->__jmpbuf)[JB_PC] = translate_address(pc);
        _buffer->__mask_was_saved = 1;
      }
    }
    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
     
    #include "uthreads.hh"
    #include "Thread.h"
    #include <cassert>
     
     
    unsigned int translate_address(unsigned int addr);
     
    void printTest() {
      printf("test");
    }
     
    int main() {
      //thread_spawn(printTest, 1);
      Thread* test = new Thread(printTest, 0);
      longjmp(test->_buffer, 1);
    }
    Et la : SEGMENTATION FAULT!!!

    J'ai enlevé quelques lignes pour plus de lisiblité mais l'essentiel est la...
    Je vous remercie d'avance pour votre aide, elle sera réellement appréciée!!

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    un rapport avec :
    Jumping to a function that has already terminated by return or longjmp is undefined.
    ? Je ne connais pas la fonction, mais de ce que j'en lis, j'ai l'impression que faire le setjmp dans le constructeur est une erreur puisque quand tu fais le longjmp tu es sorti de la fonction ?

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Je vois pas l'intérêt d'utiliser setjmp/longjmp si c'est pour faire de l'asm derrière.
    Soit tu fais tout en assembleur, soit tu utilises setjmp/longjmp pour être portable.
    Une autre possibilité serait d'utiliser setcontext/swapcontext, qui est plus facile à manipuler que setjmp/longjmp tout en étant plus efficace, mais qui ne garantira la portabilité que sur système POSIX.

    Autre chose, setjmp/longjmp pour faire des threads ça ne marchera qu'en C, pas en C++. Ça appelle les destructeurs etc. sur la plupart des compilos, ça va juste tout casser en C++.

Discussions similaires

  1. Réponses: 6
    Dernier message: 21/08/2014, 21h51
  2. Point d'entrée Longjmp introuvable dans la bibl.orauts.dll
    Par teddi dans le forum Connexions aux bases de données
    Réponses: 2
    Dernier message: 19/03/2013, 15h27
  3. question à propos de setjmp/longjmp
    Par micheldup dans le forum Langage
    Réponses: 5
    Dernier message: 13/08/2010, 14h12
  4. Réponses: 8
    Dernier message: 23/09/2006, 17h29

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