File:  [local] / rpl / src / semaphores.c
Revision 1.83: download - view: text, annotated - select for diffs - revision graph
Wed May 30 09:27:39 2018 UTC (5 years, 11 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_29, HEAD
En route vers la 4.1.29.

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

CVSweb interface <joel.bertrand@systella.fr>