File:  [local] / rpl / src / Attic / siginfo.c
Revision 1.5: download - view: text, annotated - select for diffs - revision graph
Mon Sep 6 16:50:17 2010 UTC (13 years, 8 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_0_19, HEAD
Patches pour ne pas utiliser les IPCS SystemV qui sont bugguées jusqu'à la
moëlle sous OS/2.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.0.19
    4:   Copyright (C) 1989-2010 Dr. BERTRAND Joël
    5: 
    6:   This file is part of RPL/2.
    7: 
    8:   RPL/2 is free software; you can redistribute it and/or modify it
    9:   under the terms of the CeCILL V2 License as published by the french
   10:   CEA, CNRS and INRIA.
   11:  
   12:   RPL/2 is distributed in the hope that it will be useful, but WITHOUT
   13:   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14:   FITNESS FOR A PARTICULAR PURPOSE.  See the CeCILL V2 License
   15:   for more details.
   16:  
   17:   You should have received a copy of the CeCILL License
   18:   along with RPL/2. If not, write to info@cecill.info.
   19: ================================================================================
   20: */
   21: 
   22: 
   23: #define __BROKEN_SIGINFO_ROUTINES__
   24: #include "rpl-conv.h"
   25: 
   26: #ifdef _BROKEN_SIGINFO
   27: 
   28: #define longueur_queue  256
   29: #define nombre_queues   13
   30: 
   31: static int              *fifos;
   32: static int              markov;
   33: static sem_t            *semaphores[nombre_queues];
   34: static sem_t            *semaphore_global;
   35: 
   36: #ifdef IPCS_SYSV
   37: #ifndef OS2
   38: static unsigned char    *chemin = NULL;
   39: #endif
   40: #endif
   41: 
   42: #ifdef OS2
   43: PVOID                   ptr_os2;
   44: #else
   45: static int              segment;
   46: #endif
   47: 
   48: static unsigned char *
   49: nom_segment(unsigned char *chemin, pid_t pid)
   50: {
   51:     unsigned char               *fichier;
   52: 
   53: #   ifdef IPCS_SYSV
   54: 
   55: #   ifndef OS2
   56: 
   57:     if ((fichier = malloc((strlen(chemin) + 1 + 256 + 1) *
   58:             sizeof(unsigned char))) == NULL)
   59:     {
   60:         return(NULL);
   61:     }
   62: 
   63:     sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid);
   64: 
   65: #   else
   66: 
   67:     if ((fichier = malloc((10 + 256 + 1) * sizeof(unsigned char))) == NULL)
   68:     {
   69:         return(NULL);
   70:     }
   71: 
   72:     sprintf(fichier, "\\SHAREMEM\\RPL-SIGQUEUES-%d", (int) pid);
   73: 
   74: #   endif
   75: #   else
   76: 
   77:     if ((fichier = malloc((1 + 256 + 1) *
   78:             sizeof(unsigned char))) == NULL)
   79:     {
   80:         return(NULL);
   81:     }
   82: 
   83:     sprintf(fichier, "/RPL-SIGQUEUES-%d", (int) pid);
   84: 
   85: #   endif
   86: 
   87:     return(fichier);
   88: }
   89: 
   90: static unsigned char *
   91: nom_semaphore(pid_t pid, int queue)
   92: {
   93:     unsigned char               *fichier;
   94: 
   95:     if ((fichier = malloc((256 + 1) * sizeof(unsigned char))) == NULL)
   96:     {
   97:         return(NULL);
   98:     }
   99: 
  100:     sprintf(fichier, "/RPL-SIGSEMAPHORES-%d-%d", (int) pid, queue);
  101: 
  102:     return(fichier);
  103: }
  104: 
  105: static inline int
  106: queue_de_signal(int signal)
  107: {
  108:     switch(signal)
  109:     {
  110:         case SIGINT:
  111:             return(0);
  112:         case SIGTSTP:
  113:             return(1);
  114:         case SIGCONT:
  115:             return(2);
  116:         case SIGURG:
  117:             return(3);
  118:         case SIGPIPE:
  119:             return(4);
  120:         case SIGALRM:
  121:             return(5);
  122:         case SIGFSTOP:
  123:             return(6);
  124:         case SIGSTART:
  125:             return(7);
  126:         case SIGINJECT:
  127:             return(8);
  128:         case SIGABORT:
  129:             return(9);
  130:         case SIGFABORT:
  131:             return(10);
  132:         case SIGSEGV:
  133:             return(11);
  134:         case SIGBUS:
  135:             return(12);
  136:     }
  137: 
  138:     return(-1);
  139: }
  140: 
  141: void
  142: creation_fifos_signaux(struct_processus *s_etat_processus)
  143: {
  144:     /*
  145:      * Signaux utilisés
  146:      * SIGINT, SIGTSTP, SIGCONT, SIGURG, SIGPIPE, SIGALRM, SIGFSTOP,
  147:      * SIGSTART, SIGINJECT, SIGABORT, SIGFABORT
  148:      */
  149: 
  150:     int                             i;
  151: 
  152:     unsigned char                   *nom;
  153: 
  154: #   ifndef IPCS_SYSV // POSIX
  155: 
  156:     if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,
  157:             getpid())) == NULL)
  158:     {
  159:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  160:         return;
  161:     }
  162: 
  163:     if ((segment = shm_open(nom, O_RDWR | O_CREAT | O_EXCL,
  164:             S_IRUSR | S_IWUSR)) == -1)
  165:     {
  166:         free(nom);
  167:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  168:         return;
  169:     }
  170: 
  171:     if (ftruncate(segment, nombre_queues * ((2 * longueur_queue) + 4) *
  172:             sizeof(int)) == -1)
  173:     {
  174:         free(nom);
  175:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  176:         return;
  177:     }
  178: 
  179:     fifos = mmap(NULL, nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int),
  180:             PROT_READ | PROT_WRITE, MAP_SHARED, segment, 0);
  181:     close(segment);
  182: 
  183:     if (((void *) fifos) == ((void *) -1))
  184:     {
  185:         if (shm_unlink(nom) == -1)
  186:         {
  187:             free(nom);
  188:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  189:             return;
  190:         }
  191: 
  192:         free(nom);
  193:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  194:         return;
  195:     }
  196: 
  197:     free(nom);
  198: 
  199: #   else // SystemV
  200: #   ifndef OS2
  201: 
  202:     file                            *desc;
  203: 
  204:     key_t                           clef;
  205: 
  206:     // Création d'un segment de données associé au PID du processus courant
  207: 
  208:     chemin = (*s_etat_processus).chemin_fichiers_temporaires;
  209: 
  210:     if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,
  211:             getpid())) == NULL)
  212:     {
  213:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  214:         return;
  215:     }
  216: 
  217:     if ((desc = fopen(nom, "w")) == NULL)
  218:     {
  219:         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
  220:         return;
  221:     }
  222: 
  223:     fclose(desc);
  224: 
  225:     if ((clef = ftok(nom, 1)) == -1)
  226:     {
  227:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  228:         return;
  229:     }
  230: 
  231:     free(nom);
  232: 
  233:     if ((segment = shmget(clef,
  234:             nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int),
  235:             IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)
  236:     {
  237:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  238:         return;
  239:     }
  240: 
  241:     fifos = shmat(segment, NULL, 0);
  242: 
  243:     if (((void *) fifos) == ((void *) -1))
  244:     {
  245:         if (shmctl(segment, IPC_RMID, 0) == -1)
  246:         {
  247:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  248:             return;
  249:         }
  250: 
  251:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  252:         return;
  253:     }
  254: 
  255: #   else
  256: 
  257:     if ((nom = nom_segment(NULL, getpid())) == NULL)
  258:     {
  259:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  260:         return;
  261:     }
  262: 
  263:     if (DosAllocSharedMem(&ptr_os2, nom, nombre_queues *
  264:             ((2 * longueur_queue) + 4) * sizeof(int),
  265:             PAG_WRITE | PAG_READ | PAG_COMMIT) != 0)
  266:     {
  267:         free(nom);
  268:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  269:         return;
  270:     }
  271: 
  272:     free(nom);
  273:     fifos = ptr_os2;
  274: 
  275: #   endif
  276: #   endif
  277: 
  278:     /*
  279:      * Structure d'une queue
  280:      * 0 : pointeur en lecture sur le premier emplacement libre (int)
  281:      * 1 : pointeur en écriture sur le premier emplacement à lire (int)
  282:      * 2 : longueur de la queue (int)
  283:      * 3 : éléments restants (int)
  284:      * 4 à 4 + (2) : queue (int)
  285:      * 4 + (2) + 1 ) 4 + 2 * (2) : horodatage en centième de secondes.
  286:      */
  287: 
  288:     for(i = 0; i < nombre_queues; i++)
  289:     {
  290:         fifos[(i * (longueur_queue + 4))] = 0;
  291:         fifos[(i * (longueur_queue + 4)) + 1] = 0;
  292:         fifos[(i * (longueur_queue + 4)) + 2] = longueur_queue;
  293:         fifos[(i * (longueur_queue + 4)) + 3] = longueur_queue;
  294:     }
  295: 
  296:     // Création des sémaphores : un sémaphore par signal et par queue
  297:     // plus un sémaphore global pour tous les threads.
  298: 
  299:     for(i = 0; i < nombre_queues; i++)
  300:     {
  301:         if ((nom = nom_semaphore(getpid(), i)) == NULL)
  302:         {
  303:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  304:             return;
  305:         }
  306: 
  307:         // Le sémaphore est créé en écrasant si nécessaire un sémaphore
  308:         // préexistant. Comme le nom du sémaphore contient l'identifiant du
  309:         // processus, il est anormal d'avoir un sémaphore de même nom
  310:         // préexistant.
  311: 
  312:         if ((semaphores[i] = sem_open(nom, O_CREAT, S_IRUSR | S_IWUSR,
  313:                 1)) == SEM_FAILED)
  314:         {
  315:             (*s_etat_processus).erreur_systeme = d_es_semaphore;
  316:             return;
  317:         }
  318: 
  319:         free(nom);
  320:     }
  321: 
  322: 
  323:     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)
  324:     {
  325:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  326:         return;
  327:     }
  328: 
  329:     if ((semaphore_global = sem_open(nom, O_CREAT, S_IRUSR | S_IWUSR,
  330:             1)) == SEM_FAILED)
  331:     {
  332:         (*s_etat_processus).erreur_systeme = d_es_semaphore;
  333:         return;
  334:     }
  335: 
  336:     free(nom);
  337: 
  338:     markov = 0;
  339: 
  340:     return;
  341: }
  342: 
  343: void
  344: liberation_fifos_signaux(struct_processus *s_etat_processus)
  345: {
  346:     int                 i;
  347: 
  348: #   ifdef IPCS_SYSV // SystemV
  349: #   ifndef OS2
  350: 
  351:     if (shmdt(fifos) == -1)
  352:     {
  353:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  354:         return;
  355:     }
  356: 
  357: #   else
  358: 
  359:     if (DosFreeMem(fifos) != 0)
  360:     {
  361:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  362:         return;
  363:     }
  364: 
  365: #   endif
  366: #   else // POSIX
  367: 
  368:     if (munmap(fifos, nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int))
  369:             != 0)
  370:     {
  371:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  372:         return;
  373:     }
  374: 
  375: #   endif
  376: 
  377:     for(i = 0; i < nombre_queues; i++)
  378:     {
  379:         if (sem_close(semaphores[i]) != 0)
  380:         {
  381:             (*s_etat_processus).erreur_systeme = d_es_semaphore;
  382:             return;
  383:         }
  384:     }
  385: 
  386:     if (sem_close(semaphore_global) != 0)
  387:     {
  388:         (*s_etat_processus).erreur_systeme = d_es_semaphore;
  389:         return;
  390:     }
  391: 
  392:     return;
  393: }
  394: 
  395: void
  396: destruction_fifos_signaux(struct_processus *s_etat_processus)
  397: {
  398:     int                 i;
  399: 
  400:     unsigned char       *nom;
  401: 
  402: #   ifdef IPCS_SYSV // SystemV
  403: #   ifndef OS2
  404: 
  405:     if (shmdt(fifos) == -1)
  406:     {
  407:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  408:         return;
  409:     }
  410: 
  411:     if (shmctl(segment, IPC_RMID, 0) == -1)
  412:     {
  413:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  414:         return;
  415:     }
  416: 
  417:     if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,
  418:             getpid())) == NULL)
  419:     {
  420:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  421:         return;
  422:     }
  423: 
  424:     unlink(nom);
  425:     free(nom);
  426: 
  427: #   else
  428: 
  429:     if (DosFreeMem(fifos) != 0)
  430:     {
  431:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  432:         return;
  433:     }
  434: 
  435: #   endif
  436: #   else // POSIX
  437: 
  438:     if (munmap(fifos, nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int))
  439:             != 0)
  440:     {
  441:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  442:         return;
  443:     }
  444: 
  445:     if ((nom = nom_segment(NULL, getpid())) == NULL)
  446:     {
  447:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  448:         return;
  449:     }
  450: 
  451:     if (shm_unlink(nom) != 0)
  452:     {
  453:         free(nom);
  454:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  455:         return;
  456:     }
  457: 
  458:     free(nom);
  459: 
  460: #   endif
  461: 
  462:     for(i = 0; i < nombre_queues; i++)
  463:     {
  464:         if ((nom = nom_semaphore(getpid(), i)) == NULL)
  465:         {
  466:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  467:             return;
  468:         }
  469: 
  470:         if (sem_unlink(nom) != 0)
  471:         {
  472:             (*s_etat_processus).erreur_systeme = d_es_semaphore;
  473:             return;
  474:         }
  475: 
  476:         free(nom);
  477:     }
  478: 
  479:     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)
  480:     {
  481:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  482:         return;
  483:     }
  484: 
  485:     if (sem_unlink(nom) != 0)
  486:     {
  487:         (*s_etat_processus).erreur_systeme = d_es_semaphore;
  488:         return;
  489:     }
  490: 
  491:     free(nom);
  492: 
  493:     return;
  494: }
  495: 
  496: static inline int
  497: horodatage()
  498: {
  499:     int             ts;
  500: 
  501:     struct timeval  tv;
  502: 
  503:     gettimeofday(&tv, NULL);
  504:     ts = (int) ((tv.tv_sec * 100) + (tv.tv_usec / 10000));
  505: 
  506:     return(ts);
  507: }
  508: 
  509: int
  510: queue_in(pid_t pid, int signal)
  511: {
  512:     int             queue;
  513:     int             *base;
  514:     int             *buffer;
  515:     int             horodatage_initial;
  516: #   ifndef OS2
  517:     int             identifiant;
  518: #   endif
  519:     int             *projection_fifos;
  520: 
  521:     sem_t           *semaphore;
  522: 
  523:     queue = queue_de_signal(signal);
  524: 
  525:     unsigned char   *nom;
  526: 
  527: #   ifndef IPCS_SYSV
  528: 
  529:     // Ouverture des projections
  530: 
  531:     if ((nom = nom_segment(NULL, pid)) == NULL)
  532:     {
  533:         return(-1);
  534:     }
  535: 
  536:     // Dans le cas de SIGSTART, premier signal envoyé à un processus fils,
  537:     // il convient d'attendre que le fichier support soit effectivement
  538:     // accessible. Dans tous les autres cas, ce fichier doit exister. S'il
  539:     // n'existe plus, le processus associé n'existe plus.
  540: 
  541:     if (signal == SIGSTART)
  542:     {
  543:         horodatage_initial = horodatage();
  544: 
  545:         while((identifiant = shm_open(nom, O_RDWR, S_IRUSR | S_IWUSR)) == -1)
  546:         {
  547:             if (abs(horodatage_initial - horodatage()) > 500)
  548:             {
  549:                 return(-1);
  550:             }
  551:         }
  552:     }
  553:     else
  554:     {
  555:         if ((identifiant = shm_open(nom, O_RDWR, S_IRUSR | S_IWUSR)) == -1)
  556:         {
  557:             return(-1);
  558:         }
  559:     }
  560: 
  561:     projection_fifos = mmap(NULL, nombre_queues * ((2 * longueur_queue) + 4)
  562:             * sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, identifiant, 0);
  563:     close(identifiant);
  564: 
  565:     if (((void *) projection_fifos) == ((void *) -1))
  566:     {
  567:         return(-1);
  568:     }
  569: 
  570: #   else // Traitement à l'aide d'IPCS SystemV
  571: 
  572: #   ifndef OS2
  573:     key_t           clef;
  574: 
  575:     struct stat     s_stat;
  576: #   endif
  577: 
  578:     // Dans le cas de SIGSTART, premier signal envoyé à un processus fils,
  579:     // il convient d'attendre que le fichier support soit effectivement
  580:     // accessible. Dans tous les autres cas, ce fichier doit exister. S'il
  581:     // n'existe plus, le processus associé n'existe plus.
  582: 
  583: #   ifndef OS2
  584: 
  585:     // Ouverture des projections
  586: 
  587:     if ((nom = nom_segment(chemin, pid)) == NULL)
  588:     {
  589:         return(-1);
  590:     }
  591: 
  592:     if (signal == SIGSTART)
  593:     {
  594:         // On attend que le fichier sois présent
  595: 
  596:         horodatage_initial = horodatage();
  597: 
  598:         while(stat(nom, &s_stat) != 0)
  599:         {
  600:             if (abs(horodatage_initial - horodatage()) > 500)
  601:             {
  602:                 return(-1);
  603:             }
  604:         }
  605:     }
  606: 
  607:     if ((clef = ftok(nom, 1)) == -1)
  608:     {
  609:         return(-1);
  610:     }
  611: 
  612:     free(nom);
  613: 
  614:     if (signal == SIGSTART)
  615:     {
  616:         while((identifiant = shmget(clef,
  617:                 nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int),
  618:                 S_IRUSR | S_IWUSR)) == -1);
  619:     }
  620:     else
  621:     {
  622:         if ((identifiant = shmget(clef,
  623:                 nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int),
  624:                 S_IRUSR | S_IWUSR)) == -1)
  625:         {
  626:             return(-1);
  627:         }
  628:     }
  629: 
  630:     projection_fifos = shmat(identifiant, NULL, 0);
  631: 
  632:     if (((void *) projection_fifos) == ((void *) -1))
  633:     {
  634:         return(-1);
  635:     }
  636: 
  637: #   else
  638: 
  639:     // Ouverture des projections
  640: 
  641:     if ((nom = nom_segment(NULL, pid)) == NULL)
  642:     {
  643:         return(-1);
  644:     }
  645: 
  646:     if (signal == SIGSTART)
  647:     {
  648:         horodatage_initial = horodatage();
  649: 
  650:         while(DosGetNamedSharedMem(&ptr_os2, nom,
  651:                 PAG_READ | PAG_WRITE | PAG_COMMIT) != 0)
  652:         {
  653:             if (abs(horodatage_initial - horodatage()) > 500)
  654:             {
  655:                 return(-1);
  656:             }
  657:         }
  658:     }
  659:     else
  660:     {
  661:         if (DosGetNamedSharedMem(&ptr_os2, nom,
  662:                 PAG_READ | PAG_WRITE) != 0)
  663:         {
  664:             return(-1);
  665:         }
  666:     }
  667: 
  668:     projection_fifos = ptr_os2;
  669:     
  670: #   endif
  671: #   endif
  672: 
  673:     if ((nom = nom_semaphore(pid, queue)) == NULL)
  674:     {
  675: #       ifdef IPCS_SYSV
  676: #       ifndef OS2
  677:         shmdt(projection_fifos);
  678: #       else
  679:         DosFreeMem(projection_fifos);
  680: #       endif
  681: #       else
  682:         munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)
  683:                 * sizeof(int));
  684: #       endif
  685:         return(-1);
  686:     }
  687: 
  688:     while((semaphore = sem_open(nom, 0)) == SEM_FAILED);
  689:     free(nom);
  690: 
  691:     while(sem_wait(semaphore) != 0)
  692:     {
  693:         if (errno != EINTR)
  694:         {
  695: #           ifdef IPCS_SYSV
  696: #           ifndef OS2
  697:             shmdt(projection_fifos);
  698: #           else
  699:             DosFreeMem(projection_fifos);
  700: #           endif
  701: #           else
  702:             munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)
  703:                     * sizeof(int));
  704: #           endif
  705:             return(-1);
  706:         }
  707:     }
  708: 
  709:     base = &(projection_fifos[(longueur_queue + 4) * queue]);
  710:     buffer = &(base[4]);
  711: 
  712:     // base[3] contient le nombre d'éléments restants
  713: 
  714:     if (base[3] <= 0)
  715:     {
  716:         sem_post(semaphore);
  717:         sem_close(semaphore);
  718: #       ifdef IPCS_SYSV
  719: #       ifndef OS2
  720:         shmdt(projection_fifos);
  721: #       else
  722:         DosFreeMem(projection_fifos);
  723: #       endif
  724: #       else
  725:         munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)
  726:                 * sizeof(int));
  727: #       endif
  728:         return(-1);
  729:     }
  730: 
  731:     base[3]--;
  732: 
  733:     // base[1] contient le prochain élément à écrire
  734: 
  735:     buffer[base[1] + (nombre_queues * base[2])] = horodatage();
  736:     buffer[base[1]++] = (int) pid;
  737:     base[1] %= base[2];
  738: 
  739:     if (sem_post(semaphore) != 0)
  740:     {
  741: #       ifdef IPCS_SYSV
  742: #       ifndef OS2
  743:         shmdt(projection_fifos);
  744: #       else
  745:         DosFreeMem(projection_fifos);
  746: #       endif
  747: #       else
  748:         munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)
  749:                 * sizeof(int));
  750: #       endif
  751:         sem_close(semaphore);
  752:         return(-1);
  753:     }
  754: 
  755:     sem_close(semaphore);
  756: 
  757:     // Fermeture des projections
  758: #   ifdef IPCS_SYSV
  759: #   ifndef OS2
  760:     shmdt(projection_fifos);
  761: #   else
  762:     DosFreeMem(projection_fifos);
  763: #   endif
  764: #   else
  765:     munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)
  766:             * sizeof(int));
  767: #   endif
  768: 
  769:     return(0);
  770: }
  771: 
  772: static inline int
  773: chaine_markov(int markov, int delta)
  774: {
  775:     double      memoire = 0.9;
  776:     int         valeur;
  777: 
  778:     valeur = (int) ((memoire * markov) + ((1 - memoire) * delta));
  779:     valeur = (valeur < 10) ? 10 : valeur;
  780: 
  781:     return(valeur);
  782: }
  783: 
  784: pid_t
  785: origine_signal(int signal)
  786: {
  787:     logical1        drapeau;
  788: 
  789:     int             *base;
  790:     int             *buffer;
  791:     int             delta;
  792:     int             pid;
  793:     int             queue;
  794: 
  795:     queue = queue_de_signal(signal);
  796: 
  797:     BUG(queue == -1, uprintf("[%d] Unknown signal %d in this context\n",
  798:             (int) getpid(), signal));
  799: 
  800:     while(sem_wait(semaphores[queue]) != 0)
  801:     {
  802:         if (errno != EINTR)
  803:         {
  804:             return(-1);
  805:         }
  806:     }
  807: 
  808:     // On retire les interruptions anciennes qui ont été ratées sauf s'il
  809:     // s'agit de la dernière dans la queue.
  810: 
  811:     base = &(fifos[(longueur_queue + 4) * queue]);
  812:     buffer = &(base[4]);
  813: 
  814:     if (base[3] == (base[2] - 1))
  815:     {
  816:         delta = abs(horodatage() -
  817:                  buffer[base[0] + (nombre_queues * base[2])]);
  818:         // Une seule interruption dans la queue.
  819:         pid = buffer[base[0]++];
  820:         base[0] %= base[2];
  821:         base[3]++;
  822: 
  823:         markov = chaine_markov(markov, delta);
  824:     }
  825:     else if (base[3] >= base[2])
  826:     {
  827:         // Aucune interruption n'est dans la queue.
  828:         // On a retiré trop d'interruptions de la queue.
  829: 
  830:         // (base[3] - base[2]) + 1 : nombre d'interruptions manquantes
  831:         // base[0] - 1             : dernière interruption lue
  832:         pid = buffer[((((base[0] + base[2] - 1) % base[2])
  833:                 - ((base[3] - base[2]) + 1)) + base[2]) % base[2]];
  834: 
  835:         if (kill(pid, 0) != 0)
  836:         {
  837:             pid = getpid();
  838:         }
  839:     }
  840:     else
  841:     {
  842:         // Plusieurs interruptions à distribuer.
  843:         drapeau = d_vrai;
  844: 
  845:         do
  846:         {
  847:             delta = abs(horodatage() -
  848:                      buffer[base[0] + (nombre_queues * base[2])]);
  849:             pid = buffer[base[0]++];
  850:             base[0] %= base[2];
  851:             base[3]++;
  852: 
  853:             if ((delta > (2 * markov)) && (base[3] < base[2]))
  854:             {
  855:                 drapeau = d_vrai;
  856:             }
  857:             else
  858:             {
  859:                 drapeau = d_faux;
  860:             }
  861:         } while(drapeau == d_vrai);
  862: 
  863:         markov = chaine_markov(markov, delta);
  864:     }
  865: 
  866:     if (sem_post(semaphores[queue]) != 0)
  867:     {
  868:         return(-1);
  869:     }
  870: 
  871:     return((pid_t) pid);
  872: }
  873: 
  874: int
  875: kill_broken_siginfo(pid_t pid, int signal)
  876: {
  877:     int                 ios;
  878: 
  879:     sem_t               *semaphore;
  880: 
  881:     unsigned char       *nom;
  882: 
  883:     /*
  884:      * Lorsqu'on veut interrompre le processus pid, on ouvre le segment
  885:      * correspondant au processus en question et ou ajoute le pid dans la
  886:      * queue.
  887:      *
  888:      * Le sémaphore global à tous les threads d'un même processus sert
  889:      * à garantir que les signaux seront traités dans l'ordre de ce qui est
  890:      * effectivement mis dans la queue.
  891:      */
  892: 
  893:     // Sémaphore acquis
  894: 
  895:     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)
  896:     {
  897:         return(-1);
  898:     }
  899: 
  900:     while((semaphore = sem_open(nom, 0)) == SEM_FAILED);
  901:     free(nom);
  902: 
  903:     while(sem_wait(semaphore) != 0)
  904:     {
  905:         if (errno != EINTR)
  906:         {
  907:             return(-1);
  908:         }
  909:     }
  910: 
  911:     if ((signal != 0) && (signal != SIGINT))
  912:     {
  913:         if (queue_in(pid, signal) != 0)
  914:         {
  915:             sem_post(semaphore);
  916:             sem_close(semaphore);
  917:             return(-1);
  918:         }
  919:     }
  920: 
  921:     ios = kill(pid, signal);
  922: 
  923:     // Sémaphore relâché
  924: 
  925:     sem_post(semaphore);
  926:     sem_close(semaphore);
  927: 
  928:     return(ios);
  929: }
  930: 
  931: int
  932: pthread_kill_broken_siginfo(pthread_t tid, int signal)
  933: {
  934:     int                 ios;
  935: 
  936:     sem_t               *semaphore;
  937: 
  938:     unsigned char       *nom;
  939: 
  940:     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)
  941:     {
  942:         return(-1);
  943:     }
  944: 
  945:     while((semaphore = sem_open(nom, 0)) == SEM_FAILED);
  946:     free(nom);
  947: 
  948:     while(sem_wait(semaphore) != 0)
  949:     {
  950:         if (errno != EINTR)
  951:         {
  952:             return(-1);
  953:         }
  954:     }
  955: 
  956:     if ((signal != 0) && (signal != SIGINT))
  957:     {
  958:         if (queue_in(getpid(), signal) != 0)
  959:         {
  960:             sem_post(semaphore);
  961:             sem_close(semaphore);
  962:             return(-1);
  963:         }
  964:     }
  965: 
  966:     ios = pthread_kill(tid, signal);
  967: 
  968:     sem_post(semaphore);
  969:     sem_close(semaphore);
  970: 
  971:     return(ios);
  972: }
  973: 
  974: #endif
  975: 
  976: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>