paulo_54 | Bonjour tous,
J’écris un logiciel qui émule une machine qui a existé il y a maintenant plus de 25 ans. Il s’agit d’un ordinateur à base de MC6801/3 (un ancien processeur / microcontroleur 8 bits de Motorola) qui opérait l’OS Flex2.
Un bout de code de duplique fork() puis chaque branche ouvre un terminal (xterm, urxvt ou autre konsole), l’un exécutant l’émulateur avec son moniteur-débugger et l’autre simulant simplement une VT52. J’usqu’à maintenant, pas de problème, et le projet est bien avancé, bien qu'il reste beaucoup à faire. Il existe une commande du débogeur/moniteur qui permet de générer une interruption du processeur émulé (NMI ou IRQ), et cette partie fonctionne bien.
J’ai voulu être interrompu régulièrement (comme le matériel d’antan) et ai utilisé setitimer() pour ça. Mode ITIMER_REAL → SIGALRM. Tout fonctionne bien (!) si ce n’est que le programme d’émulation s’arrête. J’ai beau chercher à savoir pourquoi, rien n’y fait : je ne trouve pas. Je ne sais pas où me mettre (avec le débogeur DDD) pour voir d’où vient le problème. J’imagine qu’un autre signal (d’erreur, probablement) est généré et que le handler par défaut de ce signal provoque l’abandon, mais je n’imagine pas de solution pour intercepter afin de débugger.
Notez qu'à un moment, j'ai essayé de faire envoyer des signaux SIGUSR1 à la partie debugger-moniteur, par la partie VT52, qui n'a guère que ça à faire, et j'ai eu le même problème. Il s'agit certainement de quelque chose de bien connu par ceux qui ont chatouillé les signaux, mais suis trop tarte, sans doute : Je ne sais pas d'où ça vient et ne sais pas comment faire pour le trouver, et donc y remédier !
extraits:
Code :
- pthread_mutex_t tiMut=PTHREAD_MUTEX_INITIALIZER;
- sig_atomic_t mSC=0;
- static void EmuEndPeriod (void) { // void (and !int sig) To escape the warning
- /// **************************************************************************
- /* The handler is invoqued with SIGALRM (|SIGPROF|SIGVTALRM) signa. The
- kBitIRQ of _6303.IrqFlgs or kBitNMI of _6303.IrqFlgs will be set to initiate
- an interrution while stepping. As in the real word, it is the responsability
- of the emulated program to "acknowledge" the concerned bit. */
- pthread_mutex_lock(&tiMut); //sig=0; // To escape the warning
- mSC+=1; // EmuIsGone ? _6303.IrqFlgs|=kBitNMI :0; // Sets the bit NMI
- pthread_mutex_unlock(&tiMut);
- }
- int EmuStep (void) {
- /// **************************************************************************
- // Returns 0 if the opcode [_EmuGetMem(_6303.Pc)] is invalide
- …
- pthread_mutex_lock(&tiMut);
- if ((i=mSC))
- mSC=0;
- pthread_mutex_unlock(&tiMut);
- if (i) {
- if (gTimer2_NMI) {
- if(!(gRunner2-=i) || gRunner2&kBit(15)) { // Expiration if virtualy <0
- gRunner2=gTimer2_NMI+gRunner2; // Re-init the timer
- _6303.IrqFlgs|=kBitNMI; // Sets the bit NMI
- }
- }
- if (gTimer4_IRQ) {
- if(!(gRunner4-=i) || gRunner4&kBit(15)) { // Expiration if 0
- gRunner4=gTimer4_IRQ+gRunner4; // Re-init the timer
- _6303.IrqFlgs|=kBitIRQ; // Sets the bit IRQ
- }
- }
- }
- /** Interruption treatment is placed here to permit the execution of at least
- one instruction after the registers had been pushed in stack.
- One of the 10 bits corresponding to the IRQ is set somewhere in this function
- (see EmuSpcActLeave(), above). See IrqFlgs definition NOTE */
- if (_6303.IrqFlgs) { // All bits
- if (_6303.IrqFlgs&kBitRST) { // Immediat and unconditional action
- _6303.IrqFlgs&=~kBitRST;
- EmuReset();
- return(1);
- }
- else if ((_6303.IrqFlgs&kBitNMI) && // NMInterrupt request
- ((_6303.IrqPre^_6303.IrqFlgs)&kBitNMI)) // Falling edge (↑ indeed)
- EmuEnterIt(Vect_NMI);
- else if ((_6303.IrqFlgs&kBitIRQ) && (!(_6303.Cc&kI)))
- EmuEnterIt(Vect_IRQ);
- }
- _6303.IrqPre=_6303.IrqFlgs; // Note of the current state (solely for NMI)
- …
|
L’"allumage" du timer:
Code :
- const struct itimerval gPeriod={{ 2, 10000 }, { 2, 10000 }};
- void SetFreeRunner (void) {
- /// **************************************************************************
- // ITIMER_REAL:SIGALRM | ITIMER_VIRTUAL:SIGVTALRM | ITIMER_PROF:SIGPROF
- static struct sigaction sa;
- memset(&sa, 0, sizeof (sa));
- sa.sa_handler=(void(*)(int))&EmuEndPeriod;
- sigaction(SIGALRM, &sa, NULL);
- if (setitimer(ITIMER_REAL, &gPeriod, NULL)<0) //
- PerrExit("setitimer() a provoqué une erreur", 1);
- }
|
Vous aurez probablement compris que ma question est : savez-vous comment je pourrais me sortir de là ?
À noter que je placerai le tout en ligne et sous licence GNU. S'il vous tente de jeter un œil sur le projet, faites le moi savoir.
Je vous remercie pour l'attention que vous aurez porté à ce post.
Cordialement |