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; } }Et la : SEGMENTATION FAULT!!!
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); }
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!!
Partager