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

Linux Discussion :

pthread.h/semaphore.h ordre de blocage et de reveil


Sujet :

Linux

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 760
    Points : 626
    Points
    626
    Par défaut pthread.h/semaphore.h ordre de blocage et de reveil
    Bonjour,

    Je suis assez nouveau dans l'utilisation des threads et des semaphores en C. J'ai assimilé l'API cependant il me reste un probleme de comprehension.
    Est ce que l'ordre de blocage des threads correspond a celui de reveil ou est ce au programmateur de s'en charger ?
    Autrement dit j'ai deux threads A et B, et une ressource protegee par un semaphore R. A prend R. B se bloque donc en attente de R. Un troisieme thread C est cree et de meme se bloque en attente de R. A lache R. Que se passe t il ?
    Est on assuré que B prenne la ressource (l'ordre de blocage correspond alors a l'ordre de reveil) ou se peut il que cela soit n'importe lequel, aussi bien B que C ?

    D'avance merci.

  2. #2
    Membre confirmé Avatar de Lunixinclar
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2006
    Messages
    416
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 416
    Points : 489
    Points
    489
    Par défaut
    Salut,

    Pour en être sûr je te propose de jeter un oeil au barbier http://www.linux-france.org/article/...r/barbier.html
    Thread A: le barbier,
    Thread B: un client,
    et sémaphore sur le nombre places assises disponibles.

    Modifies-le pour passer le nom du client au barbier et ainsi vérifier l'ordre de passage.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 760
    Points : 626
    Points
    626
    Par défaut
    Merci, mais bon j'ai pas envi de tout lire.
    Je serais capable de coder un test (et je l'ai fait) mais le probleme, c'est que l'on ne peut faire un test certain. Car Il n'y a pas moyen de connaitre l'ordre de blocage des threads...

    Edit : http://www.opengroup.org/pubs/online.../sem_post.html m'apporte peut etre une reponse, il faut savoir ce qu'est _POSIX_PRIORITY_SCHEDULING et quel est son support...

  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 : 68
    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 TabrisLeFol
    mais le probleme, c'est que l'on ne peut faire un test certain. Car Il n'y a pas moyen de connaitre l'ordre de blocage des threads...

    Edit : http://www.opengroup.org/pubs/online.../sem_post.html m'apporte peut etre une reponse, il faut savoir ce qu'est _POSIX_PRIORITY_SCHEDULING et quel est son support...
    Mauvaise approche.

    Le principe des threads est d'avoir des instructions bloquantes (suspensions, wait, I/O synchrones) et d'être indépendants.

    Si tu veux tout synchroniser, utilise les sémaphores mais avant, demande toi si une application par thread a un sens dans ton cas.

  5. #5
    Membre Expert

    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juin 2003
    Messages
    4 506
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 506
    Points : 5 723
    Points
    5 723
    Par défaut
    Autrement dit j'ai deux threads A et B, et une ressource protegee par un semaphore R. A prend R. B se bloque donc en attente de R. Un troisieme thread C est cree et de meme se bloque en attente de R. A lache R. Que se passe t il ?
    Est on assuré que B prenne la ressource (l'ordre de blocage correspond alors a l'ordre de reveil) ou se peut il que cela soit n'importe lequel, aussi bien B que C ?
    La réponse est je ne sais pas.Cela peut être le B un coup et le C un autre coup. SUr certains système comme solaris c'est déja plus déterministe...

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 760
    Points : 626
    Points
    626
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Le principe des threads est d'avoir des instructions bloquantes (suspensions, wait, I/O synchrones) et d'être indépendants.
    Justement, mes threads sont independants, ils font tous un calcul different mais a la fin ils ont besoin d'un acces a une meme ressource que je vais donc synchroniser a l'aide d'un semaphore.
    Mon probleme est juste au niveau "logique" autrement dit pouvoir etre sur qu'un thread n'attende pas en vain cette ressource car il se fait "doubler" par d'autres threads qui on demandés la ressource plus tard. Je ne veut pas m'arreter a "il arrivera bien a un moment ou a un autre a prendre la ressource".

    D'apres ce que j'ai compris de la doc, il y a moyen de fixer une strategie FIFO (je connais pas l'autre ) et dans ce cas la, si cela est supporté, cela me conviendrait. Je vais essayer (quand j'aurais le temps).

    Mais il y a peut etre d'autres solution, comme faire son propre gestionnaire mais si cela est deja codé que ce soit dans le noyau ou la bibliotheque, je prefere reutiliser le travail deja fait.

  7. #7
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 681
    Points
    18 681
    Par défaut
    si cela peut t'aider voici de quoi jouer...


    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
    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
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    #include <sys/types.h>
    #include <fcntl.h>
    #include <semaphore.h>
    #include <signal.h>
    #include <unistd.h>
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string>
     
    #define ALLOW_OTHER_PROCESS 0
     
    class Semaphore {
            public:
                    static const int WAIT_FOREVER = -1;
                    static int num;
     
            protected:
                    sem_t id;
                    char name[20];
                    Semaphore() { 
                            sprintf(name,"sem_%d",num);
                            num++;
                            if (num >= SEM_VALUE_MAX) {
                                    printf("attention nombre maximal de semaphores a
    tteint\n");
                            }
                    }
                    Semaphore(sem_t id) : id(id) { strcpy(name,"\0"); }
     
            public:
                    virtual bool take(int to) { return (sem_wait(&id) == 0); }
                    void take() { take(WAIT_FOREVER); }
                    virtual void give() { 
                            if (sem_post(&id) != 0)
                                    perror("Semaphore::give() failure in sem_post\n"
    );
                    }
                    virtual void flush() { 
                            int tmp;
                            do {
                                    sem_getvalue(&id,&tmp);
                            } while (tmp > 0);
                    }
                    virtual ~Semaphore() { sem_destroy(&id); }
    };
    int Semaphore::num = 1;
     
    class Mutex : public Semaphore {
            public:
                    Mutex() : Semaphore() { 
                            if (sem_init(&id, ALLOW_OTHER_PROCESS, 1) < 0) {
                                    perror("sem_init failure in Mutex()\n");
                            }
                    }
    };
     
    class CountSema : public Semaphore {
            protected:
                    int count;
                    Mutex countMtx;
     
            public:
                    CountSema(int init=0) : Semaphore() {
                            if (sem_init(&id, ALLOW_OTHER_PROCESS, init) < 0) {
                                    perror("sem_init failure in CountSema()\n");
                            }
                            count = init;
                    }
                    virtual ~CountSema() { }
     
                    virtual bool take(int to) {
                            countMtx.take();
                            count--;
                            if (count < 0) {
                                    countMtx.give();
                                    if (sem_wait(&id) == 0) {
                                            countMtx.take();
                                            count++;
                                            countMtx.give();
                                            return false;
                                    } 
                            } else {
                                    countMtx.give();
                            }
     
                            return true;
                    }
     
                    virtual void give() {
                            countMtx.take();
                            if (count < 0)
                                    if (sem_post(&id) != 0) {
                                            perror("sem_post failure in CountSema::g
    ive()\n");
                                    }
                            count++;
                            countMtx.give();
                    }
     
                    virtual void flush() {
                            countMtx.take();
                            while (count > 0) {
                                    if (sem_post(&id) != 0)
                                            perror("CountSema::flush() failure in se
    m_post\n");
                                    count--;
                            }
                            count = 0;
                            countMtx.give();
                    }
     
                    virtual int getCount() {
                            return count;
                    }
    }; 
     
    class BinSema : public Semaphore {      
            public:
                    BinSema(bool init=false) : Semaphore() {
                            if (sem_init(&id, ALLOW_OTHER_PROCESS, ((init) ? 1 : 0))
     < 0) {
                                    perror("sem_init failure in BinSema()\n");
                            }
                            ;
                    }
    };
     
     
    static void* _c_run(void* pt);
     
    class Thread {
            public:
                    static int num;
     
            protected:
                    const int stackSize;
                    int prio;
                    virtual void run() = 0;
                    pthread_t* id;
                    BinSema joinSem;
                    Mutex idMtx;
                    char name[20];
     
            public:
                    Thread(int _prio, int _stackSize) : stackSize(_stackSize), prio(
    _prio), id(NULL) {
                            sprintf(name,"thread_%d",num);
                    }
                    virtual ~Thread() {
                            if (id != NULL) {
                                    pthread_cancel(*id);
                                    free(id);
                            }
                           joinSem.flush();
                    }
     
                    void start() {
                            idMtx.take();
                            if (id == NULL) {
                                    id = (pthread_t*) malloc(sizeof(pthread_t));
                                    if (pthread_create(id, NULL, _c_run, (void*) thi
    s) != 0) {
                                            perror("Thread::start() failure in pthre
    ad_create\n");
                                            free(id);
                                    }
                                    idMtx.give();
                            } else {
                                    idMtx.give();
                                    throw "Thread non demarre";
                            }
                    }
     
                    void join() {
                            idMtx.take();
                            if (id != 0) {
                                    idMtx.give();
                                    joinSem.take();
                            } else
                                    idMtx.give();
                    }
     
            friend void* _c_run(void* p);
    };
    int Thread::num = 1;
     
    static void* _c_run(void* arg) {
            Thread* pt = (Thread*) arg;
            pt->run();
            pt->joinSem.flush();
            free(pt->id);
    }

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 760
    Points : 626
    Points
    626
    Par défaut
    En C, c'est plutot difficil d'avoir des classes.

  9. #9
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 681
    Points
    18 681
    Par défaut
    Citation Envoyé par TabrisLeFol
    En C, c'est plutot difficil d'avoir des classes.

    mais faire une conception sur le modèle objet est C en trivial...

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 760
    Points : 626
    Points
    626
    Par défaut
    En effet la conception en C serait possible, mais pas trivial pour moi. C'est vrai qu'avoir des classes enveloppes peut faire plus propre mais cela ne resout pas mon problem de sheduling.

    En ce qui le concerne, le sheduling sched_setscheduler requiere d'etre en root afin de pouvoir mettre en place un SCHED_FIFO ou SCHED_RR, donc j'abandonne ces solutions. Mon probleme est donc quel est le comportement de sem_post en sachant que l'on est en SCHED_OTHER, et que _POSIX_PRIORITY_SCHEDULING est defini.
    D'apres une doc, la seule chose que je sais est

    If the symbol _POSIX_PRIORITY_SCHEDULING is defined, the thread to be unblocked will be chosen in a manner appropriate to the scheduling policies and parameters in effect for the blocked threads.
    mais cela me dit pas grand chose. Peut etre que la specifiaction ne peut aller plus loin, mais ne peut on pas avoir plus de renseignement sur l'implementation ? (sans regarder le source...)

  11. #11
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Points : 28 129
    Points
    28 129
    Par défaut
    Bonjour,

    Prenons le cas de 3 threads, qui ont chacun finit leur travail, et essayent d'accéder à ta ressource R.

    Est-ce que l'ordre compte pour toi ? C'est à dire est-ce que tu obtiens un résulat différent si on A, puis B puis C qui prennent le sméphore de si on a A puis C puis B ?
    Si la réponse est oui, alors il te faut une synchronisation forte, dans laquelle A réveille B qui va réveiller C.

    Si en revanche tu te fous de l'ordre, alors j'avoue ne pas bien voir ton problème.

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 760
    Points : 626
    Points
    626
    Par défaut
    Non mon probleme n'est pas exactement l'ordre mais j'aimerais prouver (avoir la certitude) qu'un thread accede "rapidement" a cette ressource.
    Par rapidement, j'entends que la possibilitée qu'il se fasse doubler par tous les threads suivants est impossible. (Et par thread suivants, threads ayant demandés R apres ce thread.)
    C'est un pire cas, mais cela montre le probleme. En cas de rush sur cette ressource, j'aimerais ne pas faire d'injustice.
    (Un peu comme eviter de faire mourir un philosophe... )

    Le control des threads doit etre gere par le noyau linux (j'utilise 2.4 et 2.6), a moins que cela soit fait par dessus mais je n'arrive pas a trouver des documentations la dessus... (Comme je le disais sem_post est vague)

Discussions similaires

  1. Pthread et semaphores
    Par Yabo dans le forum Linux
    Réponses: 9
    Dernier message: 30/03/2008, 01h09
  2. ORDER BY dans un ordre inhabituel
    Par Riam dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 21/03/2003, 14h29
  3. Ordre de parcours de l'arbre...
    Par Sylvain James dans le forum XML/XSL et SOAP
    Réponses: 3
    Dernier message: 01/12/2002, 19h41
  4. [Kylix] Blocage Kylix 3
    Par DevX dans le forum EDI
    Réponses: 2
    Dernier message: 13/11/2002, 21h29
  5. [] Tri d'un tableau par ordre alphabétique
    Par cafeine dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 17/09/2002, 09h43

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