File:  [local] / rpl / src / semaphores.c
Revision 1.89: download - view: text, annotated - select for diffs - revision graph
Fri Jan 10 11:15:51 2020 UTC (4 years, 2 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_32, HEAD
Modification du copyright.

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

CVSweb interface <joel.bertrand@systella.fr>