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

C Discussion :

sauvegarde d'un contexte, plus precisément d'une adresse a exécuter


Sujet :

C

  1. #1
    Membre à l'essai
    Homme Profil pro
    mécatronique
    Inscrit en
    Septembre 2014
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : mécatronique

    Informations forums :
    Inscription : Septembre 2014
    Messages : 23
    Points : 16
    Points
    16
    Par défaut sauvegarde d'un contexte, plus precisément d'une adresse a exécuter
    Bonjour, me revoila sur le forum avec un nouveau problème, voila je code un OS temps réel et j'ai un petit soucis pour sauvegarder un "contexte"
    j'explique mon cas:
    je suis en train d'exécuter une tache i, cette tache requiert a un moment donner un événement qui n'est pas encore arrivé. Donc la tache s'arrète de s'exécuter en plein milieu pour attendre cet événement.
    En attendant je réalise d'autre opération ..... lorsque que l'événement arrive pour débloquer la tache 1, je doit retourner précisément à l'endroit ou je me suis arrété.
    Comment faire pour enregistrer cette adresse? Assembleur ou C

    Je travaille sur PIC32
    cordialement

  2. #2
    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 518
    Points
    41 518
    Par défaut
    Normalement lors d'une interruption, on empile simplement l'adresse de retour (et tous les autres registres aussi, d'ailleurs, il n'y a pas de "scratch registers" pour les interruptions), non?
    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.

  3. #3
    Membre à l'essai
    Homme Profil pro
    mécatronique
    Inscrit en
    Septembre 2014
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : mécatronique

    Informations forums :
    Inscription : Septembre 2014
    Messages : 23
    Points : 16
    Points
    16
    Par défaut
    oui sa fonctionne bien pour les interruprions, or la il ne s'agit pas d'une véritable interruption, (exemple timer, interruption externe ...) la c'est le programme qui va par exemple déclarer l'événement débloqué, donc quand le programme aura détecté que l'événement est débloqué, il faudra que le program counter aille à la tache i à l'endroit ou elle c'est arrété
    Donc il faut je pense que je sauvegarde l'endroit ou elle s'est arrété pour y retourné après. Mais je ne sais pas comment récuperer l'adresse a exécuter.

    Exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Tache1()
    {
       j'exécute des instructions
       . 
       .
       je doit disposer d'un évenement pour continuer, la tache se met en suspend
       je doit reprendre ICI l'exécution de la tache
       .
       .
    }
    et en attendant l'événement j'exécute d'autres taches.

  4. #4
    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 518
    Points
    41 518
    Par défaut
    Ça ressemble tout simplement à deux threads, ça. Et le changement de contexte, qu'il soit ou non à l'initiative du thread, compte comme l'interrompant et doit marcher de manière similaire. Dans ce cas-là, il me semble que la sauvegarde est plutôt dans la structure de données décrivant le thread auprès du kernel plutôt que dans l'une ou l'autre pile, en l'absence d'un besoin de récursion...
    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.

  5. #5
    Membre à l'essai
    Homme Profil pro
    mécatronique
    Inscrit en
    Septembre 2014
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : mécatronique

    Informations forums :
    Inscription : Septembre 2014
    Messages : 23
    Points : 16
    Points
    16
    Par défaut
    bah en faite oui j'ai décrit pour chaque structure de tache un emplacement pour sauvegarder l'emplacement a reprendre. Enfin je crois que je ne comprend pas ta réponse, désolé

    la en faite je souhaiterais arréter la première tache complétement et revenir que plus tard. donc le threads 1 est arréter

  6. #6
    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 518
    Points
    41 518
    Par défaut
    C'est typiquement ce qui se passe dans une fonction d'attente.
    Cela se passe dans le kernel avec la complicité du scheduler. Une fonction d'attente, une fois passée en kernel-mode, doit:
    • Régler des informations indiquant quel(s) objet(s) de synchronisation peu(ven)t réveiller le thread.
    • Marquer le thread comme "en attente" pour que le scheduler ne le re-sélectionne pas.
    • Contacter le scheduler pour qu'il fasse un changement de contexte maintenant, sans attendre l'expiration de son timer.

    Quand le second thread signalera l'objet de synchronisation pour indiquer la fin de sa tâche, cela causera un autre appel kernel-mode, qui changera l'état du premier thread de "en attente" à "prêt à exécuter". Le scheduler fera le reste quand son timer sonnera (ou quand le second thread se terminera complètement, vu que ça aussi, ça cause probablement un changement de contexte anticipé).
    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.

  7. #7
    Membre à l'essai
    Homme Profil pro
    mécatronique
    Inscrit en
    Septembre 2014
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : mécatronique

    Informations forums :
    Inscription : Septembre 2014
    Messages : 23
    Points : 16
    Points
    16
    Par défaut
    ok je voit ce que tu veut dire, alors j'ai essayé de mettre en attente le premier thread, en attente de l'événement et j'espere que le timer relance de nouvelles interruptions et donc de nouveau la fonction schedule. Or il ne le fait pas. En effet je pense que comme lorsqu'il y a une interruption, la fonction interruption est ouverte et ne peut pas se réouvrir.

    voila le code de l'interruption:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ISR2( iinterruptTIMER2)//routine d'interruption du timer 2, cadencement de l'ordonnanceur
    {
            interrupt_TIMER2_flag_off()
            Error = Schedule();
            if(Error != E_OK)//si on a une reeur
            {
                ErrorHook(Error);
                ShutdownOS (Error);
            }
            LancementTache();             
    }

    et quand je bloque la tache 1, je fait appelle a une fonction qui regarde si l'événement est disponible sinon elle attend qu'il le soit, donc le ISR2 reste ouvert.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
            while((EVENT_REG&Mask)==0){/*on attend que l'événement arrive
                                      en attendant des interruptions du timer 2 provoque des ordonancement*/}
            printf("l'evenement reprend, la tache est arrivee\n");
    comment puit je faire pour que les interruptions tu timer se déroule normalement?

  8. #8
    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 518
    Points
    41 518
    Par défaut
    Normalement, l'attente d'un objet de synchronisation n'est pas censée être active.
    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.

  9. #9
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut Sauvegarde d'un contexte, plus precisément d'une adresse a exécuter
    Bonsoir
    Juste une suggestion, si c'est vraiment une restauration de contexte que tu veux en langage C système, pourquoi ne pas utiliser les primitives existant sous UNIX cela te faciliterait la tâche
    en utilisant les primitives suivantes setjmp & longjmp dont l'un sauvegarde le contexte actuel et l'autre la restaures tu pourrais très bien réaliser ce que tu veux avec ça ? plus d'avis serait la bienvenue
    Exemple plus courant détection d'une division par 0

    Code C : 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
     
    #include <stdio.h>
    #include <signal.h>
    #include <setjmp.h>
     
    #define ALR	1
    #define MIN	50
    #define MAX	100
     
    int i;
    int ret;
     
    jmp_buf rest_Context;
    struct sigaction s_Event;
     
    /***
    *       Handler
    ***/
    void h_Sig( void ){
     
    	printf("#Dectection division par Zéro à la tâche %d\n ", i);
    	longjmp( rest_Context, ALR );
    }
     
    /***
    *       Fonctyion divisition
    ***/
    int f_Calcul( int iArg ){
     
    	return ( MIN /  ( ( iArg * iArg)  - MAX ) );
    }
     
    /***
    *       Fonction principale
    ***/
    int main( void ){
     
    	int iRet = 0;
    	(&s_Event)->sa_handler = h_Sig;
    	sigaction( SIGFPE, &s_Event, NULL );
     
    	for( i = 0; i < MIN/3; i++ ){
     
    		iRet = setjmp( rest_Context );
    		if( iRet == 0 ){
     
    			ret = f_Calcul( i );
    			printf("Loop (%d) =\t%d\n", i, ret );
    		}
    		continue;
    	}
     
    	return ( 0 );
    }
    à bientôt
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  10. #10
    Membre à l'essai
    Homme Profil pro
    mécatronique
    Inscrit en
    Septembre 2014
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : mécatronique

    Informations forums :
    Inscription : Septembre 2014
    Messages : 23
    Points : 16
    Points
    16
    Par défaut
    Alors, j'ai essayé de jouer avec les threads, au début j'étais content car cela marcher avec un seul événement en attente, le problème c'est que si je met un autre événement en attente un autre thread s'ouvre et si je débloque le premier il ne peut pas y revenir, donc il faut vraiment une solution ou je peut sauvegarder le program counter ou la tache s'est arrétéé et y aller quand j'ai envie afin de ne pas ouvrir un grand nombre de threads qui peuvent bloquer mon programme.

    Je ne voit pas trop comment je peut utiliser la fonction sjmp, auriez vous d'autres infos?
    merci

  11. #11
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 678
    Points
    13 678
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par antho_gpz Voir le message
    je code un OS temps réel
    Citation Envoyé par sambia39 Voir le message
    pourquoi ne pas utiliser les primitives existant sous UNIX cela te faciliterait la tâche
    Ca va être difficile d'utiliser des fonctions d'UNIX quand on code un OS...

    Mais l'idée est bonne puisque les fonctions sont en fait fournies par les normes C, elles ne sont pas spécifiques UNIX --> http://linux.die.net/man/3/longjmp
    D'ailleurs : http://ww1.microchip.com/downloads/e...User_Guide.pdf --> page 373

  12. #12
    Membre à l'essai
    Homme Profil pro
    mécatronique
    Inscrit en
    Septembre 2014
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : mécatronique

    Informations forums :
    Inscription : Septembre 2014
    Messages : 23
    Points : 16
    Points
    16
    Par défaut
    j'ai essayé dans un bout de programme avec mplab et sa compile, sa renvoit bien a la hauteur du Setjmp() donc a voir si j'arrive a me débrouiller avec ça en créant un nouveau buffer pour chaque attente

  13. #13
    Membre à l'essai
    Homme Profil pro
    mécatronique
    Inscrit en
    Septembre 2014
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : mécatronique

    Informations forums :
    Inscription : Septembre 2014
    Messages : 23
    Points : 16
    Points
    16
    Par défaut
    bonjour je reviens à vous a cause d'un autre problème lié à setjmp(buf).
    La fonction fonctionne bien, sauvegarde bien l'adresse a revenir avec le long jump. Le problème est que lorsque j'appelle la fonction setjump, elle vient m'écraser des valeurs avec un 0. je ne comprend pas du tout car j'ai regarder les adresse et elle ne sont pas les mêmes.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    setjmp(OS_TASKS[1].ptr_PC);//mémorisation de l'adresse d'arret
            WaitEvent(Event2);//regarde si l'événement est dispo ou non
            if(OS_TASKS[1].STATE!=RUNNING) return;//si la tache est en waiting on arrête, si la tache est en RUN on continue
    voila je vient stocké l'adresse de set jump dans un élément de structure mais le problème c'est que je vient écraser un autre élément plus loin dans la mémoire
    OS_TASKS[2].SCHEDULE = 0 , qui est un autre élément de la même structure a un indice près.

    j'ai donc regarder les adresses que prend setjmp(buffer)
    de 0xA0000374 , avec la valeur stocké du program counter 0x9D008C2C
    à 0xA00003D0 , les valeurs sont que des 0
    en effet il attribut pour le compilateur xc32 un tableau de 24 pour le buffer

    et la valeur qu'il change est a l'adresse 0xA00003FC,

    de plus c'est "périodique" si je fait un setjmp(OS_TASKS[2].ptr_PC), il va me modifier la structure de l'indice 3, le même élément.

    Comment faire pour éviter cela?

  14. #14
    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 518
    Points
    41 518
    Par défaut
    Setjmp n'agit pas que sur le pointeur d'instruction, il agit aussi sur le pointeur de pile. Et pour cela il n'est fiable que pour remonter dans la pile, et peut-être à bas niveau, pour sauter d'une pile à l'autre. En aucun cas il ne doit être utilisé pour retourner dans une fonction qui s'est déjà terminée.

    Normalement le changement de contexte d'un thread à l'autre (chaque thread ayant sa propre pile), je pense que c'est le genre de partie d'un OS qu'on code en assembleur. Mais peut-être que dans ce cas précis, un usage judicieux de setjmp() peut suffire...
    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.

  15. #15
    Membre à l'essai
    Homme Profil pro
    mécatronique
    Inscrit en
    Septembre 2014
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : mécatronique

    Informations forums :
    Inscription : Septembre 2014
    Messages : 23
    Points : 16
    Points
    16
    Par défaut
    oui je pense que le setjmp() je peut oublier ...
    Cependant en assembleur je ne sais pas du tout comment avoir accès à la "stack" pour connaitre par exemple le PC de l'instruction suivante.

    voila le jeu d'instruction dont je dispose:
    http://www.johnloomis.org/microchip/...tructions.html

  16. #16
    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 518
    Points
    41 518
    Par défaut
    Ah, là on entre sur un territoire inconnu pour moi, celui des processeurs sans pile... On peut toujours faire des piles bien sûr, mais elles sont alors en software (par exemple, l'opcode le plus proche d'un "jump to subroutine" semble être "jump and link", qui semble mettre l'adresse de retour dans un registre au lieu de l'empiler...).

    Il serait intéressant de voir l'assembleur généré par ton compilateur C sur cette plate-forme.

    De plus, cette doc ne dit pas vraiment dans quelles circonstances on accède aux registres Shadow...
    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.

Discussions similaires

  1. Déterminer la Valeur la plus grande dans une table
    Par arnaud_verlaine dans le forum Langage SQL
    Réponses: 9
    Dernier message: 23/08/2014, 00h35
  2. Marqueur KML le plus proche d'une adresse
    Par josse34 dans le forum APIs Google
    Réponses: 0
    Dernier message: 29/06/2013, 18h18
  3. Recherche plus restrictive sur une adresse
    Par Mides dans le forum IGN API Géoportail
    Réponses: 4
    Dernier message: 04/04/2013, 17h03
  4. sauvegarder une adresse et la récupérer plus tard
    Par nbs1522 dans le forum Débuter
    Réponses: 6
    Dernier message: 11/01/2013, 11h37
  5. [langage] Substitution précise dans une chaine
    Par ATPase dans le forum Langage
    Réponses: 4
    Dernier message: 02/04/2004, 15h57

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