Diff for /rpl/src/semaphores.c between versions 1.4 and 1.13

version 1.4, 2010/06/24 10:10:47 version 1.13, 2010/08/26 19:07:42
Line 1 Line 1
 /*  /*
 ================================================================================  ================================================================================
   RPL/2 (R) version 4.0.17    RPL/2 (R) version 4.0.19
   Copyright (C) 1989-2010 Dr. BERTRAND Joël    Copyright (C) 1989-2010 Dr. BERTRAND Joël
   
   This file is part of RPL/2.    This file is part of RPL/2.
Line 20 Line 20
 */  */
   
   
 #ifdef SEMAPHORES_NOMMES  #include "rpl-conv.h"
 #include "rpl.conv.h"  
   
   #ifdef SEMAPHORES_NOMMES
   
 /*  /*
 ================================================================================  ================================================================================
Line 40  sem_t * Line 40  sem_t *
 sem_init2(unsigned int valeur, enum t_semaphore semaphore)  sem_init2(unsigned int valeur, enum t_semaphore semaphore)
 {  {
     snprintf(noms_semaphores[semaphore], LONGUEUR_NOM_SEMAPHORE,      snprintf(noms_semaphores[semaphore], LONGUEUR_NOM_SEMAPHORE,
             "/RPLSEM-%d-%llu-%d", (int) getpid(),              "/RPL-SEM-%d-%llu-%d", (int) getpid(),
             (unsigned long long) pthread_self(),              (unsigned long long) pthread_self(),
             (int) semaphore);              (int) semaphore);
     return(sem_open(noms_semaphores[semaphore], O_CREAT,      return(sem_open(noms_semaphores[semaphore], O_CREAT,
Line 106  sem_getvalue2(sem_t *semaphore, int *val Line 106  sem_getvalue2(sem_t *semaphore, int *val
 }  }
   
 #endif  #endif
   
   #ifdef SEMAPHORES_SYSV
   
   /*
   ================================================================================
     Fonctions d'émulation de sémaphores POSIX en fonction des sémaphores SysV
   ================================================================================
     Entrées :
   --------------------------------------------------------------------------------
     Sorties :
   --------------------------------------------------------------------------------
     Effets de bord : néant
   ================================================================================
   */
   
   #ifndef OS2
       extern unsigned char *chemin_semaphores_SysV;
   #else
       unsigned char racine_semaphores_OS2[] = "\\SEM32\\";
       unsigned char racine_memoire_OS2[] = "\\SHAREDMEM\\";
   #endif
   
   int
   sem_init_SysV(sem_t *semaphore, int shared, unsigned int valeur)
   {
       // Création d'un sémaphore anonyme qui devra être supprimé par
       // sem_destroy_SysV
   #   ifndef OS2
   
       int             ios;
   
       union semun     argument;
   
       if (shared != 0)
       {
           errno = ENOSYS;
           return(-1);
       }
   
       (*semaphore).sem = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL |
               S_IRUSR | S_IWUSR);
       (*semaphore).path = NULL;
       (*semaphore).pid = getpid();
   
       if ((*semaphore).sem == -1)
       {
           errno = EINVAL;
           return(-1);
       }
   
       argument.val = valeur;
       ios = semctl((*semaphore).sem, 0, SETVAL, argument);
   
       return(ios);
   
   #   else
   
       sem_t           *psem;
   
       psem = semaphore;
   
       if (shared != 0)
       {
           errno = ENOSYS;
           return(-1);
       }
   
       if (((*psem).cnt = malloc(sizeof(ULONG))) == NULL)
       {
           free(psem);
           errno = ENOMEM;
           return(-1);
       }
   
       if (((*psem).nopened = malloc(sizeof(ULONG))) == NULL)
       {
           free((*psem).cnt);
           free(psem);
           errno = ENOMEM;
           return(-1);
       }
   
       if (DosCreateMutexSem(NULL, &((*psem).hmtx), 0, 0) != 0)
       {
           free((*psem).cnt);
           free((*psem).nopened);
           free(psem);
           return(-1);
       }
   
       if (DosCreateEventSem(NULL, &((*psem).hev), 0, (valeur != 0) ? 1 : 0) != 0)
       {
           DosCloseMutexSem((*psem).hmtx);
           free((*psem).cnt);
           free((*psem).nopened);
           free(psem);
           return(-1);
       }
   
       (*(*psem).cnt) = valeur;
       (*(*psem).nopened) = 1;
       (*psem).shared = shared;
       (*psem).allocated = 0;
   
       return(0);
   
   #   endif
   }
   
   int
   sem_destroy_SysV(sem_t *semaphore)
   {
       // Détruit un sémaphore anonmyme
   #   ifndef OS2
   
       if ((*semaphore).path != NULL)
       {
           return(EINVAL);
       }
   
       if ((*semaphore).pid != getpid())
       {
           return(0);
       }
   
       if (semctl((*semaphore).sem, 0, IPC_RMID) == -1)
       {
           return(EINVAL);
       }
   
       return(0);
   
   #   else
   
       sem_t       *psem;
   
       psem = semaphore;
   
       if (DosRequestMutexSem((*psem).hmtx, SEM_INDEFINITE_WAIT) != 0)
       {
           return(EINVAL);
       }
   
       if (DosCloseMutexSem((*psem).hmtx) != 0)
       {
           return(EINVAL);
       }
   
       while(DosCloseEventSem((*psem).hev) == ERROR_SEM_BUSY)
       {
           DosPostEventSem((*psem).hev);
       }
   
       (*(*psem).nopened)--;
   
       if ((*psem).shared == 0)
       {
           free((*psem).cnt);
           free((*psem).nopened);
       }
       else
       {
           if ((*(*psem).nopened) == 0)
           {
               DosFreeMem((*psem).cnt);
           }
       }
   
       if ((*psem).allocated != 0)
       {   
           free(psem);
       }
   
       return(0);
   
   #   endif
   }
   
   int
   sem_wait_SysV(sem_t *semaphore)
   {
   #   ifndef OS2
   
       struct sembuf       commande;
   
       commande.sem_num = 0;
       commande.sem_op = -1;
       commande.sem_flg = 0;
   
       while(semop((*semaphore).sem, &commande, 1) == -1)
       {
           if (errno != EINTR)
           {
               errno = EINVAL;
               return(-1);
           }
       }
   
       return(0);
   
   #   else
   
       sem_t       *psem;
   
       ULONG       cnt;
   
       psem = semaphore;
   
       if (DosWaitEventSem((*psem).hev, SEM_INDEFINITE_WAIT) != 0)
       {
           errno = EINVAL;
           return(-1);
       }
   
       if (DosRequestMutexSem((*psem).hmtx, SEM_INDEFINITE_WAIT) != 0)
       {
           errno = EINVAL;
           return(-1);
       }
   
       if ((*(*psem).cnt) > 0)
       {
           (*(*psem).cnt)--;
       }
   
       if ((*(*psem).cnt) == 0)
       {
           DosResetEventSem((*psem).hev, &cnt);
       }
   
       DosReleaseMutexSem((*psem).hmtx);
       return(0);
   
   #   endif
   }
   
   int
   sem_trywait_SysV(sem_t *semaphore)
   {
   #   ifndef OS2
   
       struct sembuf       commande;
   
       commande.sem_num = 0;
       commande.sem_op = -1;
       commande.sem_flg = IPC_NOWAIT;
   
       while(semop((*semaphore).sem, &commande, 1) == -1)
       {
           if (errno != EINTR)
           {
               errno = EINVAL;
               return(-1);
           }
       }
   
       return(0);
   
   #   else
   
       int         ios;
   
       sem_t       *psem;
   
       ULONG       cnt;
   
       psem = semaphore;
   
       if ((ios = DosWaitEventSem((*psem).hev, SEM_IMMEDIATE_RETURN)) != 0)
       {
           errno = (ios == ERROR_TIMEOUT) ? EAGAIN : EINVAL;
           return(-1);
       }
   
       if (DosRequestMutexSem((*psem).hmtx, SEM_INDEFINITE_WAIT) != 0)
       {
           errno = EINVAL;
           return(-1);
       }
   
       if ((*(*psem).cnt) > 0)
       {
           (*(*psem).cnt)--;
       }
   
       if ((*(*psem).cnt) == 0)
       {
           DosResetEventSem((*psem).hev, &cnt);
       }
   
       DosReleaseMutexSem((*psem).hmtx);
       return(0);
   
   #   endif
   }
   
   int
   sem_post_SysV(sem_t *semaphore)
   {
   #   ifndef OS2
   
       struct sembuf       commande;
   
       commande.sem_num = 0;
       commande.sem_op = 1;
       commande.sem_flg = 0;
   
       while(semop((*semaphore).sem, &commande, 1) == -1)
       {
           if (errno != EINTR)
           {
               errno = EINVAL;
               return(-1);
           }
       }
   
       return(0);
   
   #   else
   
       sem_t               *psem;
   
       psem = semaphore;
   
       if (DosRequestMutexSem((*psem).hmtx, SEM_INDEFINITE_WAIT) != 0)
       {
           errno = EINVAL;
           return(-1);
       }
   
       (*(*psem).cnt)++;
       DosPostEventSem((*psem).hev);
       DosReleaseMutexSem((*psem).hmtx);
   
       return(0);
   
   #   endif
   }
   
   int
   sem_getvalue_SysV(sem_t *semaphore, int *valeur)
   {
   #   ifndef OS2
   
       (*valeur) = semctl((*semaphore).sem, 0, GETVAL);
   
       if ((*valeur) < 0)
       {
           return(EINVAL);
       }
   
       return(0);
   
   #   else
   
       sem_t               *psem;
   
       psem = semaphore;
   
       if (DosRequestMutexSem((*psem).hmtx, SEM_INDEFINITE_WAIT) != 0)
       {
           errno = EINVAL;
           return(-1);
       }
   
       (*valeur) = (*(*psem).cnt);
       DosReleaseMutexSem((*psem).hmtx);
   
       return(0);
   
   #   endif
   }
   
   sem_t
   *sem_open_SysV(const char *nom, int oflag, ...)
   //*sem_open(const char *nom, int oflag)
   //*sem_open(const char *nom, int oflag, mode_t mode, unsigned int value)
   {
       mode_t              mode;
   
       sem_t               *semaphore;
   
   #   ifndef OS2
       file                *desc;
   
       key_t               clef;
   
       union semun         argument;
   #   endif
   
       unsigned char       *nom_absolu;
   
       unsigned int        valeur;
   
       va_list             liste;
   
   #   ifdef OS2
       sem_t               *psem;
   
       PVOID               base;
   
       unsigned char       *ptr;
       unsigned char       *nom_segment;
   #   endif
   
   #   ifndef OS2
   
       if ((nom_absolu = malloc((strlen(chemin_semaphores_SysV) + strlen(nom)
               + 1) * sizeof(unsigned char))) == NULL)
       {
           return(SEM_FAILED);
       }
   
       sprintf(nom_absolu, "%s%s", chemin_semaphores_SysV, nom);
   
       if ((semaphore = malloc(sizeof(sem_t))) == NULL)
       {
           return(SEM_FAILED);
       }
   
   #   else
   
       if ((nom_segment = malloc((strlen(racine_memoire_OS2) + strlen(nom) + 1)
               * sizeof(unsigned char))) == NULL)
       {
           return(SEM_FAILED);
       }   
   
       sprintf(nom_segment, "%s%s", racine_memoire_OS2, nom);
       ptr = nom_segment;
   
       while((*ptr) != d_code_fin_chaine)
       {
           if ((*ptr) == '/')
           {
               (*ptr) = '\\';
           }
   
           ptr++;
       }
   
       if ((nom_absolu = malloc((strlen(racine_semaphores_OS2) + strlen(nom)
               + 2) * sizeof(unsigned char))) == NULL)
       {
           return(SEM_FAILED);
       }
   
       sprintf(nom_absolu, "%s%s", racine_semaphores_OS2, nom);
       ptr = nom_absolu;
   
       while((*ptr) != d_code_fin_chaine)
       {
           if ((*ptr) == '/')
           {
               (*ptr) = '\\';
           }
   
           ptr++;
       }
   
       (*(ptr + 1)) = d_code_fin_chaine;
   
       if ((psem = malloc(sizeof(sem_t))) == NULL)
       {
           return(SEM_FAILED);
       }
   
       (*psem).allocated = 1;
   
   #   endif
   
       if ((oflag & O_CREAT) == 0)
       {
           // 2 arguments
   
   #       ifndef OS2
   
           clef = ftok(nom_absolu, 1);
   
           if (clef == -1)
           {
               return(SEM_FAILED);
           }
   
           (*semaphore).sem = semget(clef, 0, 0);
           (*semaphore).path = nom_absolu;
           (*semaphore).pid = getpid();
   
           if ((*semaphore).sem == -1)
           {   
               free(semaphore);
               free(nom_absolu);
   
               return(SEM_FAILED);
           }
   
   #       else
   
           if ((psem = malloc(sizeof(sem_t))) == NULL)
           {
               free(nom_absolu);
               free(nom_segment);
               return(SEM_FAILED);
           }
   
           (*ptr) = 'M';
   
           if (DosOpenMutexSem(nom_absolu, &((*psem).hmtx)) != 0)
           {
               free(psem);
               free(nom_absolu);
               free(nom_segment);
   
               return(SEM_FAILED);
           }
   
           (*ptr) = 'S';
   
           if (DosOpenEventSem(nom_absolu, &((*psem).hev)) != 0)
           {
               DosCloseMutexSem((*psem).hmtx);
   
               free(psem);
               free(nom_absolu);
               free(nom_segment);
   
               return(SEM_FAILED);
           }
   
           if (DosGetNamedSharedMem(&base, nom_segment, PAG_WRITE | PAG_READ) != 0)
           {
               DosCloseMutexSem((*psem).hmtx);
   
               free(nom_absolu);
               free(nom_segment);
               free(psem);
   
               return(SEM_FAILED);
           }
   
           free(nom_segment);
   
           (*psem).cnt = (ULONG *) base;
           (*psem).nopened = ((ULONG *) base) + 1;
           (*psem).shared = 1;
   
           if (DosRequestMutexSem((*psem).hmtx, SEM_INDEFINITE_WAIT) != 0)
           {
               DosCloseMutexSem((*psem).hmtx);
   
               free(nom_absolu);
               free(nom_segment);
               free(psem);
   
               return(SEM_FAILED);
           }
   
           (*((*psem).nopened))++;
   
           DosReleaseMutexSem((*psem).hmtx);
   
           semaphore = psem;
   
   #       endif
       }
       else
       {
           // 4 arguments
   
           // O_CREAT O_EXCL
           // S_IRUSR S_IWUSR
   
           va_start(liste, oflag);
           mode = va_arg(liste, mode_t);
           valeur = va_arg(liste, unsigned int);
           va_end(liste);
   
   #       ifndef OS2
   
           if ((desc = fopen(nom_absolu, "w")) == NULL)
           {
               free(semaphore);
               free(nom_absolu);
   
               return(SEM_FAILED);
           }
   
           fclose(desc);
   
           if ((clef = ftok(nom_absolu, 1)) == -1)
           {
               free(semaphore);
               free(nom_absolu);
   
               return(SEM_FAILED);
           }
   
           (*semaphore).sem = semget(clef, 1,
                   (((oflag & O_CREAT) == 0) ? 0 : IPC_CREAT) |
                   (((oflag & O_EXCL) == 0) ? 0 : IPC_EXCL) |
                   (int) mode);
           (*semaphore).path = nom_absolu;
           (*semaphore).pid = getpid();
   
           if ((*semaphore).sem == -1)
           {   
               free(semaphore);
               free(nom_absolu);
   
               return(SEM_FAILED);
           }
   
           argument.val = valeur;
           semctl((*semaphore).sem, 0, SETVAL, argument);
   
   #       else
   
           if ((psem = malloc(sizeof(sem_t))) == NULL)
           {
               free(nom_absolu);
               free(nom_segment);
   
               return(SEM_FAILED);
           }
   
           (*ptr) = 'M';
   
           if (DosCreateMutexSem(nom_absolu, &((*psem).hmtx), 0, 0) != 0)
           {
               free(psem);
               free(nom_absolu);
               free(nom_segment);
   
               return(SEM_FAILED);
           }
   
           (*ptr) = 'S';
   
           if (DosCreateEventSem(nom_absolu, &((*psem).hev), 0,
                   (valeur != 0) ? 1 : 0) != 0)
           {
               DosCloseMutexSem((*psem).hmtx);
   
               free(nom_absolu);
               free(nom_segment);
               free(psem);
   
               return(SEM_FAILED);
           }
   
           if (DosAllocSharedMem(&base, nom_segment, 2 * sizeof(ULONG),
                   PAG_WRITE | PAG_READ | PAG_COMMIT) != 0)
           {
               DosCloseMutexSem((*psem).hmtx);
   
               free(nom_absolu);
               free(nom_segment);
               free(psem);
   
               return(SEM_FAILED);
           }
   
           free(nom_segment);
   
           (*psem).cnt = (ULONG *) base;
           (*psem).nopened = ((ULONG *) base) + 1;
           (*(*psem).cnt) = valeur;
           (*(*psem).nopened) = 1;
           (*psem).shared = 1;
           semaphore = psem;
   
   #       endif
       }
   
       return(semaphore);
   }
   
   int
   sem_close_SysV(sem_t *semaphore)
   {
       // Ferme un sémaphore nommé créé par sem_open_SysV()
   #   ifndef OS2
   
       if ((*semaphore).path != NULL)
       {
           free((*semaphore).path);
       }
   
       free(semaphore);
       return(0);
   
   #   else
   
       sem_t       *psem;
   
       psem = semaphore;
   
       if (DosCloseMutexSem((*psem).hmtx) != 0)
       {
           return(EINVAL);
       }
   
       while(DosCloseEventSem((*psem).hev) == ERROR_SEM_BUSY)
       {
           DosPostEventSem((*psem).hev);
       }
   
       (*(*psem).nopened)--;
   
       if ((*psem).shared == 0)
       {
           free((*psem).cnt);
           free((*psem).nopened);
       }
       else
       {
           if ((*(*psem).nopened) == 0)
           {
               DosFreeMem((*psem).cnt);
           }
       }
   
       if ((*psem).allocated != 0)
       {
           free(psem);
       }
   
       return(0);
   
   #   endif
   }
   
   int
   sem_unlink_SysV(const char *nom)
   {
       // Détruit un sémaphore nommé créé par sem_open_SysV()
   #   ifndef OS2
   
       unsigned char       *nom_absolu;
   
       if ((nom_absolu = malloc((strlen(chemin_semaphores_SysV) + strlen(nom)
               + 1) * sizeof(unsigned char))) == NULL)
       {
           return(ENOMEM);
       }
   
       sprintf(nom_absolu, "%s%s", chemin_semaphores_SysV, nom);
       semctl(semget(ftok(nom_absolu, 1), 0, 0), 0, IPC_RMID);
   
       if (unlink(nom_absolu) == -1)
       {
           free(nom_absolu);
           return(EACCES);
       }
   
       free(nom_absolu);
   
       return(0);
   
   #   else
   
       return(0);
   
   #   endif
   }
   
   #endif
   
 // vim: ts=4  // vim: ts=4

Removed from v.1.4  
changed lines
  Added in v.1.13


CVSweb interface <joel.bertrand@systella.fr>