Annotation of rpl/src/semaphores.c, revision 1.63

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

CVSweb interface <joel.bertrand@systella.fr>