File:  [local] / rpl / src / semaphores.c
Revision 1.8: download - view: text, annotated - select for diffs - revision graph
Mon Aug 9 13:51:48 2010 UTC (13 years, 8 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Ajout du support des sémaphores SystemV dans le cas où les sémaphores POSIX ne
seraient pas supportés.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.0.18
    4:   Copyright (C) 1989-2010 Dr. BERTRAND Joël
    5: 
    6:   This file is part of RPL/2.
    7: 
    8:   RPL/2 is free software; you can redistribute it and/or modify it
    9:   under the terms of the CeCILL V2 License as published by the french
   10:   CEA, CNRS and INRIA.
   11:  
   12:   RPL/2 is distributed in the hope that it will be useful, but WITHOUT
   13:   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14:   FITNESS FOR A PARTICULAR PURPOSE.  See the CeCILL V2 License
   15:   for more details.
   16:  
   17:   You should have received a copy of the CeCILL License
   18:   along with RPL/2. If not, write to info@cecill.info.
   19: ================================================================================
   20: */
   21: 
   22: 
   23: #include "rpl-conv.h"
   24: 
   25: #ifdef SEMAPHORES_NOMMES
   26: 
   27: /*
   28: ================================================================================
   29:   Fonctions d'émulation de sémaphores anonymes
   30: ================================================================================
   31:   Entrées :
   32: --------------------------------------------------------------------------------
   33:   Sorties :
   34: --------------------------------------------------------------------------------
   35:   Effets de bord : néant
   36: ================================================================================
   37: */
   38: 
   39: sem_t *
   40: sem_init2(unsigned int valeur, enum t_semaphore semaphore)
   41: {
   42:     snprintf(noms_semaphores[semaphore], LONGUEUR_NOM_SEMAPHORE,
   43:             "/RPLSEM-%d-%llu-%d", (int) getpid(),
   44:             (unsigned long long) pthread_self(),
   45:             (int) semaphore);
   46:     return(sem_open(noms_semaphores[semaphore], O_CREAT,
   47:             (S_IRUSR | S_IWUSR), valeur));
   48: }
   49: 
   50: int
   51: sem_destroy2(sem_t *semaphore_p, enum t_semaphore semaphore)
   52: {
   53:     sem_close(semaphore_p);
   54:     return(sem_unlink(noms_semaphores[semaphore]));
   55: }
   56: 
   57: #undef sem_post
   58: #undef sem_wait
   59: #undef sem_trywait
   60: 
   61: int
   62: sem_getvalue2(sem_t *semaphore, int *valeur)
   63: {
   64:     int                     i;
   65: 
   66:     logical1                drapeau_fin;
   67: 
   68:     pthread_mutex_lock(&mutex_sem);
   69: 
   70:     (*valeur) = 0;
   71:     drapeau_fin = d_faux;
   72: 
   73:     do
   74:     {
   75:         if (sem_trywait(semaphore) == -1)
   76:         {
   77:             if (errno == EAGAIN)
   78:             {
   79:                 // Le sémaphore avait une valeur nulle
   80:                 drapeau_fin = d_vrai;
   81:             }
   82:             else
   83:             {
   84:                 // Autre erreur
   85:                 pthread_mutex_unlock(&mutex_sem);
   86:                 return(-1);
   87:             }
   88:         }
   89:         else
   90:         {
   91:             (*valeur)++;
   92:         }
   93:     } while(drapeau_fin == d_faux);
   94: 
   95:     for(i = 0; i < (*valeur); i++)
   96:     {
   97:         if (sem_post(semaphore) != 0)
   98:         {
   99:             pthread_mutex_unlock(&mutex_sem);
  100:             return(-1);
  101:         }
  102:     }
  103: 
  104:     pthread_mutex_unlock(&mutex_sem);
  105:     return(0);
  106: }
  107: 
  108: #endif
  109: 
  110: #ifdef SEMAPHORES_SYSV
  111: 
  112: /*
  113: ================================================================================
  114:   Fonctions d'émulation de sémaphores POSIX en fonction des sémaphores SysV
  115: ================================================================================
  116:   Entrées :
  117: --------------------------------------------------------------------------------
  118:   Sorties :
  119: --------------------------------------------------------------------------------
  120:   Effets de bord : néant
  121: ================================================================================
  122: */
  123: 
  124: extern unsigned char *chemin_semaphores_SysV;
  125: 
  126: #ifndef UNION_SEMUN
  127: union semun
  128: {
  129:     int                 val;
  130:     struct semid_ds     *buf;
  131:     unsigned short      *array;
  132:     struct seminfo      *__buf;
  133: };
  134: #endif
  135: 
  136: int
  137: sem_init_SysV(sem_t *semaphore, int shared, unsigned int valeur)
  138: {
  139:     int             ios;
  140: 
  141:     union semun     argument;
  142: 
  143:     if (shared != 0)
  144:     {
  145:         return(ENOSYS);
  146:     }
  147: 
  148:     (*semaphore) = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | SEM_R | SEM_A);
  149: 
  150:     if ((*semaphore) == -1)
  151:     {
  152:         return(EINVAL);
  153:     }
  154: 
  155:     argument.val = valeur;
  156:     ios = semctl((*semaphore), 0, SETVAL, argument);
  157: 
  158:     return(ios);
  159: }
  160: 
  161: int
  162: sem_destroy_SysV(sem_t *semaphore)
  163: {
  164:     if (semctl((*semaphore), IPC_RMID, 0) == -1)
  165:     {
  166:         return(EINVAL);
  167:     }
  168: 
  169:     return(0);
  170: }
  171: 
  172: int
  173: sem_wait_SysV(sem_t *semaphore)
  174: {
  175:     struct sembuf       commande;
  176: 
  177:     commande.sem_num = 0;
  178:     commande.sem_op = -1;
  179:     commande.sem_flg = 0;
  180: 
  181:     if (semop((*semaphore), &commande, 1) == -1)
  182:     {
  183:         return(EINVAL);
  184:     }
  185: 
  186:     return(0);
  187: }
  188: 
  189: int
  190: sem_trywait_SysV(sem_t *semaphore)
  191: {
  192:     struct sembuf       commande;
  193: 
  194:     commande.sem_num = 0;
  195:     commande.sem_op = -1;
  196:     commande.sem_flg = IPC_NOWAIT;
  197: 
  198:     if (semop((*semaphore), &commande, 1) == -1)
  199:     {
  200:         if (errno == EAGAIN)
  201:         {
  202:             return(EAGAIN);
  203:         }
  204: 
  205:         return(EINVAL);
  206:     }
  207: 
  208:     return(0);
  209: }
  210: 
  211: int
  212: sem_post_SysV(sem_t *semaphore)
  213: {
  214:     struct sembuf       commande;
  215: 
  216:     commande.sem_num = 0;
  217:     commande.sem_op = 1;
  218:     commande.sem_flg = 0;
  219: 
  220:     if (semop((*semaphore), &commande, 1) == -1)
  221:     {
  222:         return(EINVAL);
  223:     }
  224: 
  225:     return(0);
  226: }
  227: 
  228: int
  229: sem_getvalue_SysV(sem_t *semaphore, int *valeur)
  230: {
  231:     (*valeur) = semctl((*semaphore), 0, GETVAL);
  232: 
  233:     if ((*valeur) < 0)
  234:     {
  235:         return(EINVAL);
  236:     }
  237: 
  238:     return(0);
  239: }
  240: 
  241: sem_t
  242: *sem_open_SysV(const char *nom, int oflag, ...)
  243: //*sem_open(const char *nom, int oflag)
  244: //*sem_open(const char *nom, int oflag, mode_t mode, unsigned int value)
  245: {
  246:     mode_t              mode;
  247: 
  248:     sem_t               *semaphore;
  249: 
  250:     union semun         argument;
  251: 
  252:     unsigned char       *nom_absolu;
  253: 
  254:     unsigned int        valeur;
  255: 
  256:     va_list             liste;
  257: 
  258:     if ((nom_absolu = malloc((strlen(chemin_semaphores_SysV) + strlen(nom)
  259:             + 1) * sizeof(unsigned char))) == NULL)
  260:     {
  261:         return(SEM_FAILED);
  262:     }
  263: 
  264:     sprintf(nom_absolu, "%s%s", chemin_semaphores_SysV, nom);
  265: 
  266:     if ((semaphore = malloc(sizeof(sem_t))) == NULL)
  267:     {
  268:         return(SEM_FAILED);
  269:     }
  270: 
  271:     if ((oflag & O_CREAT) == 0)
  272:     {
  273:         // 2 arguments
  274:         (*semaphore) = semget(ftok(nom_absolu, 1), 0, 0);
  275: 
  276:         if ((*semaphore) == -1)
  277:         {   
  278:             free(semaphore);
  279:             free(nom_absolu);
  280: 
  281:             return(SEM_FAILED);
  282:         }
  283:     }
  284:     else
  285:     {
  286:         // 4 arguments
  287: 
  288:         // O_CREAT O_EXCL
  289:         // S_IRUSR S_IWUSR
  290: 
  291:         va_start(liste, oflag);
  292:         mode = va_arg(liste, mode_t);
  293:         valeur = va_arg(liste, unsigned int);
  294:         va_end(liste);
  295: 
  296:         (*semaphore) = semget(ftok(nom_absolu, 1), 1,
  297:                 ((oflag & O_CREAT) == 0) ? 0 : IPC_CREAT |
  298:                 ((oflag & O_EXCL) == 0) ? 0 : IPC_EXCL |
  299:                 ((oflag & S_IRUSR) == 0) ? 0 : SEM_R |
  300:                 ((oflag & S_IWUSR) == 0) ? 0 : SEM_A);
  301: 
  302:         if ((*semaphore) == -1)
  303:         {   
  304:             free(semaphore);
  305:             free(nom_absolu);
  306: 
  307:             return(SEM_FAILED);
  308:         }
  309: 
  310:         argument.val = valeur;
  311:         semctl((*semaphore), 0, SETVAL, argument);
  312:     }
  313: 
  314:     free(nom_absolu);
  315: 
  316:     return(semaphore);
  317: }
  318: 
  319: int
  320: sem_close_SysV(sem_t *semaphore)
  321: {
  322:     free(semaphore);
  323:     return(0);
  324: }
  325: 
  326: int
  327: sem_unlink_SysV(const char *nom)
  328: {
  329:     sem_t               semaphore;
  330: 
  331:     struct sembuf       commande;
  332: 
  333:     unsigned char       *nom_absolu;
  334: 
  335:     if ((nom_absolu = malloc((strlen(chemin_semaphores_SysV) + strlen(nom)
  336:             + 1) * sizeof(unsigned char))) == NULL)
  337:     {
  338:         return(ENOMEM);
  339:     }
  340: 
  341:     sprintf(nom_absolu, "%s%s", chemin_semaphores_SysV, nom);
  342: 
  343:     if ((semaphore = semget(ftok(nom_absolu, 1), 0, 0)) == -1)
  344:     {   
  345:         free(nom_absolu);
  346:         return(EINVAL);
  347:     }
  348: 
  349:     commande.sem_num = 0;
  350:     commande.sem_op = 0;
  351:     commande.sem_flg = 0;
  352: 
  353:     if (semop(semaphore, &commande, 1) == -1)
  354:     {
  355:         free(nom_absolu);
  356:         return(EINVAL);
  357:     }
  358: 
  359:     if (semctl(semaphore, IPC_RMID, 0) == -1)
  360:     {
  361:         free(nom_absolu);
  362:         return(EINVAL);
  363:     }
  364: 
  365:     if (unlink(nom_absolu) == -1)
  366:     {
  367:         free(nom_absolu);
  368:         return(EACCES);
  369:     }
  370: 
  371:     free(nom_absolu);
  372: 
  373:     return(0);
  374: }
  375: 
  376: #endif
  377: 
  378: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>