File:  [local] / rpl / src / semaphores.c
Revision 1.80: download - view: text, annotated - select for diffs - revision graph
Wed Jun 28 09:20:39 2017 UTC (6 years, 10 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
En route pour la 4.1.27.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.27
    4:   Copyright (C) 1989-2017 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: #include "rpl-conv.h"
   24: 
   25: 
   26: // Les fonctions suivantes ne sont utilisées que dans le cas d'un
   27: // système POSIX qui ne possède pas de sémaphores anonymes. MacOS X
   28: // est dans ce cas.
   29: 
   30: static unsigned char *
   31: nom_segment_semaphore(pid_t pid, int ordre)
   32: {
   33:     unsigned char               *fichier;
   34: 
   35:     if ((fichier = sys_malloc((1 + 256 + 1) * sizeof(unsigned char))) == NULL)
   36:     {
   37:         return(NULL);
   38:     }
   39: 
   40:     sprintf(fichier, "/RPL-%llu-%d", (unsigned long long) pid, ordre);
   41:     return(fichier);
   42: }
   43: 
   44: 
   45: static unsigned char *
   46: nom_segment_semaphore_thread(pid_t pid, pthread_t tid, int ordre)
   47: {
   48:     unsigned char               *fichier;
   49: 
   50:     if ((fichier = sys_malloc((1 + 256 + 1) * sizeof(unsigned char))) == NULL)
   51:     {
   52:         return(NULL);
   53:     }
   54: 
   55:     sprintf(fichier, "/RPL-%llu-%llu-%d", (unsigned long long) pid,
   56:             (unsigned long long) tid, ordre);
   57:     return(fichier);
   58: }
   59: 
   60: 
   61: /*
   62: ================================================================================
   63:   Fonctions d'émulation de sémaphores anonymes
   64: ================================================================================
   65:   Entrées :
   66: --------------------------------------------------------------------------------
   67:   Sorties :
   68: --------------------------------------------------------------------------------
   69:   Effets de bord : néant
   70: ================================================================================
   71: */
   72: 
   73: sem_t *
   74: sem_init2(unsigned int valeur, pid_t pid, int ordre)
   75: {
   76:     sem_t                       *semaphore;
   77: 
   78:     unsigned char               *chemin;
   79:     unsigned char               *langue;
   80: 
   81:     if ((chemin = nom_segment_semaphore(pid, ordre)) == NULL)
   82:     {
   83:         return(SEM_FAILED);
   84:     }
   85: 
   86:     if ((semaphore = sem_open(chemin, O_RDWR | O_CREAT | O_EXCL,
   87:             S_IRUSR | S_IWUSR, valeur)) == SEM_FAILED)
   88:     {
   89:         if (errno == EEXIST)
   90:         {
   91:             if ((langue = getenv("LANG")) != NULL)
   92:             {
   93:                 if (strncmp(langue, "fr", 2) == 0)
   94:                 {
   95:                     uprintf("+++Attention : Le sémaphore %s préexiste !\n",
   96:                             chemin);
   97:                 }
   98:                 else
   99:                 {
  100:                     uprintf("+++Warning: %s semaphore preexists!\n", chemin);
  101:                 }
  102:             }
  103:             else
  104:             {
  105:                 uprintf("+++Warning: %s semaphore preexists!\n", chemin);
  106:             }
  107: 
  108:             if (sem_unlink(chemin) != 0)
  109:             {
  110:                 return(SEM_FAILED);
  111:             }
  112: 
  113:             semaphore = sem_open(chemin, O_RDWR | O_CREAT | O_EXCL,
  114:                     S_IRUSR | S_IWUSR, valeur);
  115:         }
  116:     }
  117: 
  118:     sys_free(chemin);
  119: 
  120:     return(semaphore);
  121: }
  122: 
  123: 
  124: sem_t *
  125: sem_init3(unsigned int valeur, pid_t pid, pthread_t tid, int ordre)
  126: {
  127:     sem_t                       *semaphore;
  128: 
  129:     unsigned char               *chemin;
  130:     unsigned char               *langue;
  131: 
  132:     if ((chemin = nom_segment_semaphore_thread(pid, tid, ordre)) == NULL)
  133:     {
  134:         return(SEM_FAILED);
  135:     }
  136: 
  137:     if ((semaphore = sem_open(chemin, O_RDWR | O_CREAT | O_EXCL,
  138:             S_IRUSR | S_IWUSR, valeur)) == SEM_FAILED)
  139:     {
  140:         if (errno == EEXIST)
  141:         {
  142:             if ((langue = getenv("LANG")) != NULL)
  143:             {
  144:                 if (strncmp(langue, "fr", 2) == 0)
  145:                 {
  146:                     uprintf("+++Attention : Le sémaphore %s préexiste !\n",
  147:                             chemin);
  148:                 }
  149:                 else
  150:                 {
  151:                     uprintf("+++Warning: %s semaphore preexists!\n", chemin);
  152:                 }
  153:             }
  154:             else
  155:             {
  156:                 uprintf("+++Warning: %s semaphore preexists!\n", chemin);
  157:             }
  158: 
  159:             semaphore = sem_open(chemin, O_RDWR | O_CREAT,
  160:                     S_IRUSR | S_IWUSR, valeur);
  161:         }
  162:     }
  163: 
  164:     sys_free(chemin);
  165: 
  166:     return(semaphore);
  167: }
  168: 
  169: 
  170: sem_t *
  171: sem_open2(pid_t pid, int ordre)
  172: {
  173:     unsigned char               *chemin;
  174: 
  175:     sem_t                       *semaphore;
  176: 
  177:     if ((chemin = nom_segment_semaphore(pid, ordre)) == NULL)
  178:     {
  179:         return(SEM_FAILED);
  180:     }
  181: 
  182:     semaphore = sem_open(chemin, O_RDWR);
  183:     sys_free(chemin);
  184: 
  185:     return(semaphore);
  186: }
  187: 
  188: 
  189: int
  190: sem_destroy2(sem_t *semaphore, pid_t pid, int ordre)
  191: {
  192:     int                         erreur;
  193: 
  194:     unsigned char               *chemin;
  195: 
  196:     sem_close(semaphore);
  197: 
  198:     if ((chemin = nom_segment_semaphore(pid, ordre)) == NULL)
  199:     {
  200:         return(1);
  201:     }
  202: 
  203:     erreur = sem_unlink(chemin);
  204:     sys_free(chemin);
  205: 
  206:     return(erreur);
  207: }
  208: 
  209: 
  210: int
  211: sem_destroy3(sem_t *semaphore, pid_t pid, pthread_t tid, int ordre)
  212: {
  213:     int                         erreur;
  214: 
  215:     unsigned char               *chemin;
  216: 
  217:     sem_close(semaphore);
  218: 
  219:     if ((chemin = nom_segment_semaphore_thread(pid, tid, ordre)) == NULL)
  220:     {
  221:         return(1);
  222:     }
  223: 
  224:     erreur = sem_unlink(chemin);
  225:     sys_free(chemin);
  226: 
  227:     return(erreur);
  228: }
  229: 
  230: 
  231: int
  232: sem_getvalue2(sem_t *semaphore, int *valeur)
  233: {
  234:     int                     i;
  235:     int                     j;
  236: 
  237:     logical1                drapeau_fin;
  238: 
  239:     struct timespec         attente;
  240: 
  241:     attente.tv_sec = 0;
  242:     attente.tv_nsec = GRANULARITE_us * 1000;
  243: 
  244:     for(j = 0; j < 100; j++)
  245:     {
  246:         if (pthread_mutex_trylock(&mutex_sem) == 0)
  247:         {
  248:             (*valeur) = 0;
  249:             drapeau_fin = d_faux;
  250: 
  251:             do
  252:             {
  253:                 if (sem_trywait(semaphore) == -1)
  254:                 {
  255:                     if (errno == EAGAIN)
  256:                     {
  257:                         // Le sémaphore avait une valeur nulle
  258:                         drapeau_fin = d_vrai;
  259:                     }
  260:                     else
  261:                     {
  262:                         // Autre erreur
  263:                         pthread_mutex_unlock(&mutex_sem);
  264:                         return(-1);
  265:                     }
  266:                 }
  267:                 else
  268:                 {
  269:                     (*valeur)++;
  270:                 }
  271:             } while(drapeau_fin == d_faux);
  272: 
  273:             for(i = 0; i < (*valeur); i++)
  274:             {
  275:                 if (sem_post(semaphore) != 0)
  276:                 {
  277:                     pthread_mutex_unlock(&mutex_sem);
  278:                     return(-1);
  279:                 }
  280:             }
  281: 
  282:             pthread_mutex_unlock(&mutex_sem);
  283:             return(0);
  284:         }
  285: 
  286:         INCR_GRANULARITE(attente.tv_nsec);
  287:     }
  288: 
  289:     // Le mutex n'a pas pu être verrouillé. On peut raisonnablement penser
  290:     // que le sémaphore est bloqué dans un sem_wait() protégé par ce mutex.
  291: 
  292:     (*valeur) = 0;
  293:     return(0);
  294: }
  295: 
  296: 
  297: #undef sem_post
  298: #undef sem_wait
  299: #undef sem_trywait
  300: 
  301: 
  302: #ifdef IPCS_SYSV
  303: 
  304: /*
  305: ================================================================================
  306:   Fonctions d'émulation de sémaphores POSIX en fonction des sémaphores SysV
  307: ================================================================================
  308:   Entrées :
  309: --------------------------------------------------------------------------------
  310:   Sorties :
  311: --------------------------------------------------------------------------------
  312:   Effets de bord : néant
  313: ================================================================================
  314: */
  315: 
  316: #ifndef OS2 // IPCS_SYSV
  317:     extern unsigned char *racine_segment;
  318: #else // OS/2
  319:     unsigned char racine_semaphores_OS2[] = "\\SEM32\\";
  320:     unsigned char racine_memoire_OS2[] = "\\SHAREMEM\\";
  321: #endif
  322: 
  323: int
  324: sem_init_SysV(sem_t *semaphore, int shared, unsigned int valeur)
  325: {
  326:     // Création d'un sémaphore anonyme qui devra être supprimé par
  327:     // sem_destroy_SysV
  328: 
  329: #   ifndef OS2 // IPCS_SYSV
  330:         int             desc;
  331:         int             ios;
  332: 
  333:         key_t           clef;
  334: 
  335:         union semun     argument;
  336: 
  337:         unsigned char   *langue;
  338: 
  339:         if (shared == 0)
  340:         {
  341:             // Sémaphore privé
  342:             (*semaphore).sem = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL |
  343:                     S_IRUSR | S_IWUSR);
  344:             (*semaphore).path = NULL;
  345:             (*semaphore).pid = getpid();
  346:             (*semaphore).tid = pthread_self();
  347:             (*semaphore).alloue = 0;
  348:         }
  349:         else
  350:         {
  351:             // Sémaphore partagé entre plusieurs processus
  352:             if (((*semaphore).path = sys_malloc((strlen(racine_segment)
  353:                     + 2 + 256 + 1) * sizeof(unsigned char))) == NULL)
  354:             {
  355:                 return(-1);
  356:             }
  357: 
  358:             sprintf((*semaphore).path, "%s/RPL-SEMAPHORE-%d-%llX-%llX",
  359:                     racine_segment, (int) getpid(),
  360:                     (long long unsigned) pthread_self(),
  361:                     (long long unsigned) semaphore);
  362: 
  363:             if ((desc = open((*semaphore).path, O_RDWR | O_CREAT | O_EXCL,
  364:                     S_IRUSR | S_IWUSR)) == -1)
  365:             {
  366:                 if (errno != EEXIST)
  367:                 {
  368:                     sys_free((*semaphore).path);
  369:                     return(-1);
  370:                 }
  371: 
  372:                 if ((langue = getenv("LANG")) != NULL)
  373:                 {
  374:                     if (strncmp(langue, "fr", 2) == 0)
  375:                     {
  376:                         uprintf("+++Attention : Le sémaphore %s préexiste !\n",
  377:                                 (*semaphore).path);
  378:                     }
  379:                     else
  380:                     {
  381:                         uprintf("+++Warning: %s semaphore preexists!\n",
  382:                                 (*semaphore).path);
  383:                     }
  384:                 }
  385:                 else
  386:                 {
  387:                     uprintf("+++Warning: %s semaphore preexists!\n",
  388:                             (*semaphore).path);
  389:                 }
  390: 
  391:                 if ((desc = open((*semaphore).path, O_RDWR | O_CREAT,
  392:                         S_IRUSR | S_IWUSR)) == -1)
  393:                 {
  394:                     sys_free((*semaphore).path);
  395:                     return(-1);
  396:                 }
  397:             }
  398: 
  399:             (*semaphore).pid = getpid();
  400:             (*semaphore).tid = pthread_self();
  401:             clef = ftok((*semaphore).path, 1);
  402:             close(desc);
  403: 
  404:             if (clef == -1)
  405:             {
  406:                 sys_free((*semaphore).path);
  407:                 return(-1);
  408:             }
  409: 
  410:             (*semaphore).alloue = 0;
  411:             (*semaphore).sem = semget(clef, 1, IPC_CREAT | IPC_EXCL |
  412:                     S_IRUSR | S_IWUSR);
  413:         }
  414: 
  415:         if ((*semaphore).sem == -1)
  416:         {
  417:             errno = EINVAL;
  418:             return(-1);
  419:         }
  420: 
  421:         argument.val = (int) valeur;
  422:         ios = semctl((*semaphore).sem, 0, SETVAL, argument);
  423: 
  424:         return(ios);
  425: #   else // OS/2
  426:         sem_t           *psem;
  427: 
  428:         psem = semaphore;
  429: 
  430:         if (((*psem).cnt = sys_malloc(sizeof(ULONG))) == NULL)
  431:         {
  432:             sys_free(psem);
  433:             errno = ENOMEM;
  434:             return(-1);
  435:         }
  436: 
  437:         if (((*psem).nopened = sys_malloc(sizeof(ULONG))) == NULL)
  438:         {
  439:             sys_free((*psem).cnt);
  440:             sys_free(psem);
  441:             errno = ENOMEM;
  442:             return(-1);
  443:         }
  444: 
  445:         if (DosCreateMutexSem(NULL, &((*psem).hmtx), 0, 0) != 0)
  446:         {
  447:             sys_free((*psem).cnt);
  448:             sys_free((*psem).nopened);
  449:             sys_free(psem);
  450:             return(-1);
  451:         }
  452: 
  453:         if (DosCreateEventSem(NULL, &((*psem).hev), 0, (valeur != 0) ? 1 : 0)
  454:                 != 0)
  455:         {
  456:             DosCloseMutexSem((*psem).hmtx);
  457:             sys_free((*psem).cnt);
  458:             sys_free((*psem).nopened);
  459:             sys_free(psem);
  460:             return(-1);
  461:         }
  462: 
  463:         (*(*psem).cnt) = valeur;
  464:         (*(*psem).nopened) = 1;
  465:         (*psem).shared = shared;
  466:         (*psem).allocated = 0;
  467: 
  468:         return(0);
  469: #   endif
  470: }
  471: 
  472: int
  473: sem_destroy_SysV(sem_t *semaphore)
  474: {
  475:     // Détruit un sémaphore anonmyme
  476: 
  477: #   ifndef OS2 // IPCS_SYSV
  478:         if ((*semaphore).path != NULL)
  479:         {
  480:             return(EINVAL);
  481:         }
  482: 
  483:         if ((*semaphore).pid != getpid())
  484:         {
  485:             return(0);
  486:         }
  487: 
  488:         if (semctl((*semaphore).sem, 0, IPC_RMID) == -1)
  489:         {
  490:             return(EINVAL);
  491:         }
  492: 
  493:         return(0);
  494: #   else // OS/2
  495:         sem_t       *psem;
  496: 
  497:         psem = semaphore;
  498: 
  499:         if (DosRequestMutexSem((*psem).hmtx, SEM_INDEFINITE_WAIT) != 0)
  500:         {
  501:             return(EINVAL);
  502:         }
  503: 
  504:         if (DosCloseMutexSem((*psem).hmtx) != 0)
  505:         {
  506:             return(EINVAL);
  507:         }
  508: 
  509:         while(DosCloseEventSem((*psem).hev) == ERROR_SEM_BUSY)
  510:         {
  511:             DosPostEventSem((*psem).hev);
  512:         }
  513: 
  514:         (*(*psem).nopened)--;
  515: 
  516:         if ((*psem).shared == 0)
  517:         {
  518:             sys_free((*psem).cnt);
  519:             sys_free((*psem).nopened);
  520:         }
  521:         else
  522:         {
  523:             if ((*(*psem).nopened) == 0)
  524:             {
  525:                 DosFreeMem((*psem).cnt);
  526:             }
  527:         }
  528: 
  529:         if ((*psem).allocated != 0)
  530:         {   
  531:             sys_free(psem);
  532:         }
  533: 
  534:         return(0);
  535: #   endif
  536: }
  537: 
  538: int
  539: sem_wait_SysV(sem_t *semaphore)
  540: {
  541: #   ifndef OS2 // IPCS_SYSV
  542:         struct sembuf       commande;
  543: 
  544:         // semop() ne renvoie pas EINTR sur un signal !
  545: 
  546:         commande.sem_num = 0;
  547:         commande.sem_op = -1;
  548:         commande.sem_flg = 0;
  549: 
  550:         if (semop((*semaphore).sem, &commande, 1) == -1)
  551:         {
  552:             if (errno != EAGAIN)
  553:             {
  554:                 errno = EINVAL;
  555:                 return(-1);
  556:             }
  557:             else
  558:             {
  559:                 return(-1);
  560:             }
  561:         }
  562: 
  563:         return(0);
  564: #   else // OS/2
  565:         sem_t       *psem;
  566: 
  567:         ULONG       cnt;
  568: 
  569:         psem = semaphore;
  570: 
  571:         if (DosWaitEventSem((*psem).hev, SEM_INDEFINITE_WAIT) != 0)
  572:         {
  573:             errno = EINVAL;
  574:             return(-1);
  575:         }
  576: 
  577:         if (DosRequestMutexSem((*psem).hmtx, SEM_INDEFINITE_WAIT) != 0)
  578:         {
  579:             errno = EINVAL;
  580:             return(-1);
  581:         }
  582: 
  583:         if ((*(*psem).cnt) > 0)
  584:         {
  585:             (*(*psem).cnt)--;
  586:         }
  587: 
  588:         if ((*(*psem).cnt) == 0)
  589:         {
  590:             DosResetEventSem((*psem).hev, &cnt);
  591:         }
  592: 
  593:         DosReleaseMutexSem((*psem).hmtx);
  594:         return(0);
  595: #   endif
  596: }
  597: 
  598: int
  599: sem_trywait_SysV(sem_t *semaphore)
  600: {
  601: #   ifndef OS2 // IPCS_SYSV
  602:         struct sembuf       commande;
  603: 
  604:         commande.sem_num = 0;
  605:         commande.sem_op = -1;
  606:         commande.sem_flg = IPC_NOWAIT;
  607: 
  608:         if (semop((*semaphore).sem, &commande, 1) == -1)
  609:         {
  610:             return(-1);
  611:         }
  612: 
  613:         return(0);
  614: #   else // OS/2
  615:         int         ios;
  616: 
  617:         sem_t       *psem;
  618: 
  619:         ULONG       cnt;
  620: 
  621:         psem = semaphore;
  622: 
  623:         if ((ios = DosWaitEventSem((*psem).hev, SEM_IMMEDIATE_RETURN)) != 0)
  624:         {
  625:             errno = (ios == ERROR_TIMEOUT) ? EAGAIN : EINVAL;
  626:             return(-1);
  627:         }
  628: 
  629:         if (DosRequestMutexSem((*psem).hmtx, SEM_INDEFINITE_WAIT) != 0)
  630:         {
  631:             errno = EINVAL;
  632:             return(-1);
  633:         }
  634: 
  635:         if ((*(*psem).cnt) > 0)
  636:         {
  637:             (*(*psem).cnt)--;
  638:         }
  639: 
  640:         if ((*(*psem).cnt) == 0)
  641:         {
  642:             DosResetEventSem((*psem).hev, &cnt);
  643:         }
  644: 
  645:         DosReleaseMutexSem((*psem).hmtx);
  646:         return(0);
  647: #   endif
  648: }
  649: 
  650: #ifndef timespeccmp
  651: #   define timespeccmp(tsp, usp, cmp) \
  652:             (((tsp)->tv_sec == (usp)->tv_sec) ? \
  653:             ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \
  654:             ((tsp)->tv_sec cmp (usp)->tv_sec))
  655: #   define timespecadd(tsp, usp, vsp) \
  656:             do { \
  657:                 (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \
  658:                 (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \
  659:                 if ((vsp)->tv_nsec >= 1000000000L) { \
  660:                     (vsp)->tv_sec++; \
  661:                     (vsp)->tv_nsec -= 1000000000L; \
  662:                 } \
  663:             } while(0)
  664: #   define timespecsub(tsp, usp, vsp) \
  665:             do { \
  666:                 (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
  667:                 (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \
  668:                 if ((vsp)->tv_nsec < 0) { \
  669:                     (vsp)->tv_sec--; \
  670:                     (vsp)->tv_nsec += 1000000000L; \
  671:                 } \
  672:             } while(0)
  673: #endif
  674: 
  675: int
  676: sem_timedwait_SysV(sem_t *sem, struct timespec *ts)
  677: {
  678:     struct timespec onems = { 0, 1000000 };
  679:     struct timespec total = { 0, 0 };
  680:     struct timespec unslept;
  681:     struct timespec elapsed;
  682:     struct timespec tmp;
  683: 
  684:     while(timespeccmp(ts, &total, >))
  685:     {
  686:         if (sem_trywait_SysV(sem) == 0)
  687:         {
  688:             return(0);
  689:         }
  690: 
  691:         if (errno != EAGAIN)
  692:         {
  693:             return(-1);
  694:         }
  695: 
  696:         nanosleep(&onems, &unslept);
  697: 
  698:         timespecsub(&onems, &unslept, &elapsed);
  699:         timespecadd(&total, &elapsed, &tmp);
  700:         total.tv_sec = tmp.tv_sec;
  701:         total.tv_nsec = tmp.tv_nsec;
  702:     }
  703: 
  704:     errno = ETIMEDOUT;
  705:     return(-1);
  706: }
  707: 
  708: int
  709: sem_post_SysV(sem_t *semaphore)
  710: {
  711: #   ifndef OS2 // IPCS_SYSV
  712:         struct sembuf       commande;
  713: 
  714:         commande.sem_num = 0;
  715:         commande.sem_op = 1;
  716:         commande.sem_flg = 0;
  717: 
  718:         while(semop((*semaphore).sem, &commande, 1) == -1)
  719:         {
  720:             if (errno != EINTR)
  721:             {
  722:                 errno = EINVAL;
  723:                 return(-1);
  724:             }
  725:         }
  726: 
  727:         return(0);
  728: #   else // OS/2
  729:         sem_t               *psem;
  730: 
  731:         psem = semaphore;
  732: 
  733:         if (DosRequestMutexSem((*psem).hmtx, SEM_INDEFINITE_WAIT) != 0)
  734:         {
  735:             errno = EINVAL;
  736:             return(-1);
  737:         }
  738: 
  739:         (*(*psem).cnt)++;
  740:         DosPostEventSem((*psem).hev);
  741:         DosReleaseMutexSem((*psem).hmtx);
  742: 
  743:         return(0);
  744: #   endif
  745: }
  746: 
  747: int
  748: sem_getvalue_SysV(sem_t *semaphore, int *valeur)
  749: {
  750: #   ifndef OS2 // IPCS_SYSV
  751:         (*valeur) = semctl((*semaphore).sem, 0, GETVAL);
  752: 
  753:         if ((*valeur) < 0)
  754:         {
  755:             return(EINVAL);
  756:         }
  757: 
  758:         return(0);
  759: #   else
  760:         sem_t               *psem;
  761: 
  762:         psem = semaphore;
  763: 
  764:         if (DosRequestMutexSem((*psem).hmtx, SEM_INDEFINITE_WAIT) != 0)
  765:         {
  766:             errno = EINVAL;
  767:             return(-1);
  768:         }
  769: 
  770:         (*valeur) = (*(*psem).cnt);
  771:         DosReleaseMutexSem((*psem).hmtx);
  772: 
  773:         return(0);
  774: #   endif
  775: }
  776: 
  777: sem_t
  778: *sem_open_SysV(const char *nom, int oflag, ...)
  779: //*sem_open(const char *nom, int oflag)
  780: //*sem_open(const char *nom, int oflag, mode_t mode, unsigned int value)
  781: {
  782:     mode_t              mode;
  783: 
  784:     sem_t               *semaphore;
  785: 
  786: #   ifndef OS2
  787:         int             desc;
  788: 
  789:         key_t           clef;
  790: 
  791:         union semun     argument;
  792: 
  793:         unsigned char   *langue;
  794: #   endif
  795: 
  796:     unsigned char       *nom_absolu;
  797: 
  798:     unsigned int        valeur;
  799: 
  800:     va_list             liste;
  801: 
  802: #   ifdef OS2
  803:         sem_t           *psem;
  804: 
  805:         PVOID           base;
  806: 
  807:         unsigned char   *ptr;
  808:         unsigned char   *nom_segment;
  809: #   endif
  810: 
  811: #   ifndef OS2 // IPCS_SYSV
  812:         if ((nom_absolu = sys_malloc((strlen(racine_segment) + strlen(nom)
  813:                 + 2) * sizeof(unsigned char))) == NULL)
  814:         {
  815:             return(SEM_FAILED);
  816:         }
  817: 
  818:         sprintf(nom_absolu, "%s/%s", racine_segment, nom);
  819: 
  820:         if ((semaphore = sys_malloc(sizeof(sem_t))) == NULL)
  821:         {
  822:             return(SEM_FAILED);
  823:         }
  824: 
  825:         (*semaphore).alloue = -1;
  826:         (*semaphore).pid = getpid();
  827:         (*semaphore).tid = pthread_self();
  828: #   else
  829:         if ((nom_segment = sys_malloc((strlen(racine_memoire_OS2) + strlen(nom)
  830:                 + 1) * sizeof(unsigned char))) == NULL)
  831:         {
  832:             return(SEM_FAILED);
  833:         }   
  834: 
  835:         sprintf(nom_segment, "%s%s", racine_memoire_OS2, nom);
  836:         ptr = nom_segment;
  837: 
  838:         while((*ptr) != d_code_fin_chaine)
  839:         {
  840:             if ((*ptr) == '/')
  841:             {
  842:                 (*ptr) = '\\';
  843:             }
  844: 
  845:             ptr++;
  846:         }
  847: 
  848:         if ((nom_absolu = sys_malloc((strlen(racine_semaphores_OS2) +
  849:                 strlen(nom) + 2) * sizeof(unsigned char))) == NULL)
  850:         {
  851:             return(SEM_FAILED);
  852:         }
  853: 
  854:         sprintf(nom_absolu, "%s%s", racine_semaphores_OS2, nom);
  855:         ptr = nom_absolu;
  856: 
  857:         while((*ptr) != d_code_fin_chaine)
  858:         {
  859:             if ((*ptr) == '/')
  860:             {
  861:                 (*ptr) = '\\';
  862:             }
  863: 
  864:             ptr++;
  865:         }
  866: 
  867:         (*(ptr + 1)) = d_code_fin_chaine;
  868: 
  869:         if ((psem = sys_malloc(sizeof(sem_t))) == NULL)
  870:         {
  871:             return(SEM_FAILED);
  872:         }
  873: 
  874:         (*psem).allocated = 1;
  875: #   endif
  876: 
  877:     if ((oflag & O_CREAT) == 0)
  878:     {
  879:         // 2 arguments
  880: 
  881: #       ifndef OS2 // IPCS_SYSV
  882:             clef = ftok(nom_absolu, 1);
  883: 
  884:             if (clef == -1)
  885:             {
  886:                 return(SEM_FAILED);
  887:             }
  888: 
  889:             (*semaphore).sem = semget(clef, 0, 0);
  890:             (*semaphore).path = nom_absolu;
  891:             (*semaphore).pid = getpid();
  892: 
  893:             if ((*semaphore).sem == -1)
  894:             {   
  895:                 sys_free(semaphore);
  896:                 sys_free(nom_absolu);
  897: 
  898:                 return(SEM_FAILED);
  899:             }
  900: #       else // OS/2
  901:             if ((psem = sys_malloc(sizeof(sem_t))) == NULL)
  902:             {
  903:                 sys_free(nom_absolu);
  904:                 sys_free(nom_segment);
  905:                 return(SEM_FAILED);
  906:             }
  907: 
  908:             (*ptr) = 'M';
  909: 
  910:             if (DosOpenMutexSem(nom_absolu, &((*psem).hmtx)) != 0)
  911:             {
  912:                 sys_free(psem);
  913:                 sys_free(nom_absolu);
  914:                 sys_free(nom_segment);
  915: 
  916:                 return(SEM_FAILED);
  917:             }
  918: 
  919:             (*ptr) = 'S';
  920: 
  921:             if (DosOpenEventSem(nom_absolu, &((*psem).hev)) != 0)
  922:             {
  923:                 DosCloseMutexSem((*psem).hmtx);
  924: 
  925:                 sys_free(psem);
  926:                 sys_free(nom_absolu);
  927:                 sys_free(nom_segment);
  928: 
  929:                 return(SEM_FAILED);
  930:             }
  931: 
  932:             if (DosGetNamedSharedMem(&base, nom_segment, PAG_WRITE | PAG_READ)
  933:                     != 0)
  934:             {
  935:                 DosCloseMutexSem((*psem).hmtx);
  936: 
  937:                 sys_free(nom_absolu);
  938:                 sys_free(nom_segment);
  939:                 sys_free(psem);
  940: 
  941:                 return(SEM_FAILED);
  942:             }
  943: 
  944:             sys_free(nom_segment);
  945: 
  946:             (*psem).cnt = (ULONG *) base;
  947:             (*psem).nopened = ((ULONG *) base) + 1;
  948:             (*psem).shared = 1;
  949: 
  950:             if (DosRequestMutexSem((*psem).hmtx, SEM_INDEFINITE_WAIT) != 0)
  951:             {
  952:                 DosCloseMutexSem((*psem).hmtx);
  953: 
  954:                 sys_free(nom_absolu);
  955:                 sys_free(nom_segment);
  956:                 sys_free(psem);
  957: 
  958:                 return(SEM_FAILED);
  959:             }
  960: 
  961:             (*((*psem).nopened))++;
  962: 
  963:             DosReleaseMutexSem((*psem).hmtx);
  964: 
  965:             semaphore = psem;
  966: #       endif
  967:     }
  968:     else
  969:     {
  970:         // 4 arguments
  971: 
  972:         // O_CREAT O_EXCL
  973:         // S_IRUSR S_IWUSR
  974: 
  975:         va_start(liste, oflag);
  976:         mode = va_arg(liste, mode_t);
  977:         valeur = va_arg(liste, unsigned int);
  978:         va_end(liste);
  979: 
  980: #       ifndef OS2 // IPCS_SYSV
  981:             if ((desc = open(nom_absolu, O_CREAT | O_EXCL | O_RDWR,
  982:                     S_IRUSR | S_IWUSR)) == -1)
  983:             {
  984:                 if (errno != EEXIST)
  985:                 {
  986:                     sys_free(semaphore);
  987:                     sys_free(nom_absolu);
  988:                     return(SEM_FAILED);
  989:                 }
  990: 
  991:                 if ((langue = getenv("LANG")) != NULL)
  992:                 {
  993:                     if (strncmp(langue, "fr", 2) == 0)
  994:                     {
  995:                         uprintf("+++Attention : Le sémaphore %s préexiste !\n",
  996:                                 nom_absolu);
  997:                     }
  998:                     else
  999:                     {
 1000:                         uprintf("+++Warning: %s semaphore preexists!\n",
 1001:                                 nom_absolu);
 1002:                     }
 1003:                 }
 1004:                 else
 1005:                 {
 1006:                     uprintf("+++Warning: %s semaphore preexists!\n",
 1007:                             nom_absolu);
 1008:                 }
 1009: 
 1010:                 if ((desc = open(nom_absolu, O_CREAT | O_RDWR,
 1011:                         S_IRUSR | S_IWUSR)) == -1)
 1012:                 {
 1013:                     sys_free(semaphore);
 1014:                     sys_free(nom_absolu);
 1015:                     return(SEM_FAILED);
 1016:                 }
 1017:             }
 1018: 
 1019:             if ((clef = ftok(nom_absolu, 1)) == -1)
 1020:             {
 1021:                 close(desc);
 1022:                 sys_free(semaphore);
 1023:                 sys_free(nom_absolu);
 1024: 
 1025:                 return(SEM_FAILED);
 1026:             }
 1027: 
 1028:             close(desc);
 1029: 
 1030:             (*semaphore).sem = semget(clef, 1,
 1031:                     (((oflag & O_CREAT) == 0) ? 0 : IPC_CREAT) |
 1032:                     (((oflag & O_EXCL) == 0) ? 0 : IPC_EXCL) |
 1033:                     (int) mode);
 1034:             (*semaphore).path = nom_absolu;
 1035:             (*semaphore).pid = getpid();
 1036: 
 1037:             if ((*semaphore).sem == -1)
 1038:             {   
 1039:                 sys_free(semaphore);
 1040:                 sys_free(nom_absolu);
 1041: 
 1042:                 return(SEM_FAILED);
 1043:             }
 1044: 
 1045:             argument.val = (int) valeur;
 1046:             semctl((*semaphore).sem, 0, SETVAL, argument);
 1047: #       else // OS/2
 1048:             if ((psem = sys_malloc(sizeof(sem_t))) == NULL)
 1049:             {
 1050:                 sys_free(nom_absolu);
 1051:                 sys_free(nom_segment);
 1052: 
 1053:                 return(SEM_FAILED);
 1054:             }
 1055: 
 1056:             (*ptr) = 'M';
 1057: 
 1058:             if (DosCreateMutexSem(nom_absolu, &((*psem).hmtx), 0, 0) != 0)
 1059:             {
 1060:                 sys_free(psem);
 1061:                 sys_free(nom_absolu);
 1062:                 sys_free(nom_segment);
 1063: 
 1064:                 return(SEM_FAILED);
 1065:             }
 1066: 
 1067:             (*ptr) = 'S';
 1068: 
 1069:             if (DosCreateEventSem(nom_absolu, &((*psem).hev), 0,
 1070:                     (valeur != 0) ? 1 : 0) != 0)
 1071:             {
 1072:                 DosCloseMutexSem((*psem).hmtx);
 1073: 
 1074:                 sys_free(nom_absolu);
 1075:                 sys_free(nom_segment);
 1076:                 sys_free(psem);
 1077: 
 1078:                 return(SEM_FAILED);
 1079:             }
 1080: 
 1081:             if (DosAllocSharedMem(&base, nom_segment, 2 * sizeof(ULONG),
 1082:                     PAG_WRITE | PAG_READ | PAG_COMMIT) != 0)
 1083:             {
 1084:                 DosCloseMutexSem((*psem).hmtx);
 1085: 
 1086:                 sys_free(nom_absolu);
 1087:                 sys_free(nom_segment);
 1088:                 sys_free(psem);
 1089: 
 1090:                 return(SEM_FAILED);
 1091:             }
 1092: 
 1093:             sys_free(nom_segment);
 1094: 
 1095:             (*psem).cnt = (ULONG *) base;
 1096:             (*psem).nopened = ((ULONG *) base) + 1;
 1097:             (*(*psem).cnt) = valeur;
 1098:             (*(*psem).nopened) = 1;
 1099:             (*psem).shared = 1;
 1100:             semaphore = psem;
 1101: #       endif
 1102:     }
 1103: 
 1104:     return(semaphore);
 1105: }
 1106: 
 1107: int
 1108: sem_close_SysV(sem_t *semaphore)
 1109: {
 1110:     // Ferme un sémaphore nommé créé par sem_open_SysV()
 1111: #   ifndef OS2 // IPCS_SYSV
 1112:         if ((*semaphore).path != NULL)
 1113:         {
 1114:             sys_free((*semaphore).path);
 1115:         }
 1116: 
 1117:         if ((*semaphore).alloue == -1)
 1118:         {
 1119:             sys_free(semaphore);
 1120:         }
 1121: 
 1122:         return(0);
 1123: #   else
 1124:         sem_t       *psem;
 1125: 
 1126:         psem = semaphore;
 1127: 
 1128:         if (DosCloseMutexSem((*psem).hmtx) != 0)
 1129:         {
 1130:             return(EINVAL);
 1131:         }
 1132: 
 1133:         while(DosCloseEventSem((*psem).hev) == ERROR_SEM_BUSY)
 1134:         {
 1135:             DosPostEventSem((*psem).hev);
 1136:         }
 1137: 
 1138:         (*(*psem).nopened)--;
 1139: 
 1140:         if ((*psem).shared == 0)
 1141:         {
 1142:             sys_free((*psem).cnt);
 1143:             sys_free((*psem).nopened);
 1144:         }
 1145:         else
 1146:         {
 1147:             if ((*(*psem).nopened) == 0)
 1148:             {
 1149:                 DosFreeMem((*psem).cnt);
 1150:             }
 1151:         }
 1152: 
 1153:         if ((*psem).allocated != 0)
 1154:         {
 1155:             sys_free(psem);
 1156:         }
 1157: 
 1158:         return(0);
 1159: #   endif
 1160: }
 1161: 
 1162: int
 1163: sem_unlink_SysV(char *nom)
 1164: {
 1165:     // Détruit un sémaphore nommé créé par sem_open_SysV()
 1166: #   ifndef OS2 // IPCS_SYSV
 1167:         semctl(semget(ftok(nom, 1), 0, 0), 0, IPC_RMID);
 1168: 
 1169:         if (unlink(nom) == -1)
 1170:         {
 1171:             return(EACCES);
 1172:         }
 1173: 
 1174:         sys_free(nom);
 1175:         return(0);
 1176: #   else
 1177:         return(0);
 1178: #   endif
 1179: }
 1180: 
 1181: #endif
 1182: 
 1183: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>