--- rpl/src/semaphores.c 2010/08/17 11:59:28 1.10 +++ rpl/src/semaphores.c 2011/09/18 18:06:01 1.30 @@ -1,7 +1,7 @@ /* ================================================================================ - RPL/2 (R) version 4.0.18 - Copyright (C) 1989-2010 Dr. BERTRAND Joël + RPL/2 (R) version 4.1.3 + Copyright (C) 1989-2011 Dr. BERTRAND Joël This file is part of RPL/2. @@ -24,6 +24,25 @@ #ifdef SEMAPHORES_NOMMES +// Les fonctions suivantes ne sont utilisées que dans le cas d'un +// système POSIX qui ne possède pas de sémaphores anonymes. MacOS X +// est dans ce cas. + +static unsigned char * +nom_segment_semaphore(pid_t pid) +{ + unsigned char *fichier; + + if ((fichier = malloc((1 + 256 + 1) * sizeof(unsigned char))) == NULL) + { + return(NULL); + } + + sprintf(fichier, "/RPL-SIGSEMAPHORE-%d", (int) pid); + return(fichier); +} + + /* ================================================================================ Fonctions d'émulation de sémaphores anonymes @@ -37,21 +56,71 @@ */ sem_t * -sem_init2(unsigned int valeur, enum t_semaphore semaphore) +sem_init2(unsigned int valeur, pid_t pid) +{ + sem_t *semaphore; + + unsigned char *chemin; + unsigned int i; + + if ((chemin = nom_segment_semaphore(pid)) == NULL) + { + return(SEM_FAILED); + } + + semaphore = sem_open(chemin, O_CREAT, (S_IRUSR | S_IWUSR), valeur); + free(chemin); + + for(i = 0; i < valeur; i++) + { + if (sem_post(semaphore) != 0) + { + sem_close(semaphore); + return(SEM_FAILED); + } + } + + return(semaphore); +} + + +sem_t * +sem_open2(pid_t pid) { - snprintf(noms_semaphores[semaphore], LONGUEUR_NOM_SEMAPHORE, - "/RPL-SEM-%d-%llu-%d", (int) getpid(), - (unsigned long long) pthread_self(), - (int) semaphore); - return(sem_open(noms_semaphores[semaphore], O_CREAT, - (S_IRUSR | S_IWUSR), valeur)); + unsigned char *chemin; + + sem_t *semaphore; + + if ((chemin = nom_segment_semaphore(pid)) == NULL) + { + return(1); + } + + semaphore = sem_open(chemin, O_RDWR); + free(chemin); + + return(semaphore); } + int -sem_destroy2(sem_t *semaphore_p, enum t_semaphore semaphore) +sem_destroy2(sem_t *semaphore, pid_t pid) { - sem_close(semaphore_p); - return(sem_unlink(noms_semaphores[semaphore])); + int erreur; + + unsigned char *chemin; + + sem_close(semaphore); + + if ((chemin = nom_segment_semaphore(pid)) == NULL) + { + return(1); + } + + erreur = sem_unlink(chemin); + free(chemin); + + return(erreur); } #undef sem_post @@ -65,6 +134,8 @@ sem_getvalue2(sem_t *semaphore, int *val logical1 drapeau_fin; + // Si on ne peut pas décrémenter le sémaphore, c'est qu'il était + // déjà nul. pthread_mutex_lock(&mutex_sem); (*valeur) = 0; @@ -107,7 +178,7 @@ sem_getvalue2(sem_t *semaphore, int *val #endif -#ifdef SEMAPHORES_SYSV +#ifdef IPCS_SYSV /* ================================================================================ @@ -125,22 +196,14 @@ sem_getvalue2(sem_t *semaphore, int *val extern unsigned char *chemin_semaphores_SysV; #else unsigned char racine_semaphores_OS2[] = "\\SEM32\\"; - unsigned char racine_memoire_OS2[] = "\\SHAREDMEM\\"; -#endif - -#ifndef UNION_SEMUN -union semun -{ - int val; - struct semid_ds *buf; - unsigned short *array; - struct seminfo *__buf; -}; + unsigned char racine_memoire_OS2[] = "\\SHAREMEM\\"; #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; @@ -153,16 +216,19 @@ sem_init_SysV(sem_t *semaphore, int shar return(-1); } - (*semaphore) = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | SEM_R | SEM_A); + (*semaphore).sem = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | + S_IRUSR | S_IWUSR); + (*semaphore).path = NULL; + (*semaphore).pid = getpid(); - if ((*semaphore) == -1) + if ((*semaphore).sem == -1) { errno = EINVAL; return(-1); } argument.val = valeur; - ios = semctl((*semaphore), 0, SETVAL, argument); + ios = semctl((*semaphore).sem, 0, SETVAL, argument); return(ios); @@ -223,9 +289,20 @@ sem_init_SysV(sem_t *semaphore, int shar int sem_destroy_SysV(sem_t *semaphore) { + // Détruit un sémaphore anonmyme # ifndef OS2 - if (semctl((*semaphore), IPC_RMID, 0) == -1) + if ((*semaphore).path != NULL) + { + return(EINVAL); + } + + if ((*semaphore).pid != getpid()) + { + return(0); + } + + if (semctl((*semaphore).sem, 0, IPC_RMID) == -1) { return(EINVAL); } @@ -289,10 +366,13 @@ sem_wait_SysV(sem_t *semaphore) commande.sem_op = -1; commande.sem_flg = 0; - if (semop((*semaphore), &commande, 1) == -1) + while(semop((*semaphore).sem, &commande, 1) == -1) { - errno = EINVAL; - return(-1); + if (errno != EINTR) + { + errno = EINVAL; + return(-1); + } } return(0); @@ -344,9 +424,13 @@ sem_trywait_SysV(sem_t *semaphore) commande.sem_op = -1; commande.sem_flg = IPC_NOWAIT; - if (semop((*semaphore), &commande, 1) == -1) + while(semop((*semaphore).sem, &commande, 1) == -1) { - return(-1); + if (errno != EINTR) + { + errno = EINVAL; + return(-1); + } } return(0); @@ -400,10 +484,13 @@ sem_post_SysV(sem_t *semaphore) commande.sem_op = 1; commande.sem_flg = 0; - if (semop((*semaphore), &commande, 1) == -1) + while(semop((*semaphore).sem, &commande, 1) == -1) { - errno = EINVAL; - return(-1); + if (errno != EINTR) + { + errno = EINVAL; + return(-1); + } } return(0); @@ -434,7 +521,7 @@ sem_getvalue_SysV(sem_t *semaphore, int { # ifndef OS2 - (*valeur) = semctl((*semaphore), 0, GETVAL); + (*valeur) = semctl((*semaphore).sem, 0, GETVAL); if ((*valeur) < 0) { @@ -510,8 +597,6 @@ sem_t return(SEM_FAILED); } - (*psem).allocated = 1; - # else if ((nom_segment = malloc((strlen(racine_memoire_OS2) + strlen(nom) + 1) @@ -559,6 +644,8 @@ sem_t return(SEM_FAILED); } + (*psem).allocated = 1; + # endif if ((oflag & O_CREAT) == 0) @@ -567,9 +654,18 @@ sem_t # ifndef OS2 - (*semaphore) = semget(ftok(nom_absolu, 1), 0, 0); + clef = ftok(nom_absolu, 1); - if ((*semaphore) == -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); @@ -678,13 +774,14 @@ sem_t return(SEM_FAILED); } - (*semaphore) = semget(clef, 1, - ((oflag & O_CREAT) == 0) ? 0 : IPC_CREAT | - ((oflag & O_EXCL) == 0) ? 0 : IPC_EXCL | - ((oflag & S_IRUSR) == 0) ? 0 : SEM_R | - ((oflag & S_IWUSR) == 0) ? 0 : SEM_A); + (*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) == -1) + if ((*semaphore).sem == -1) { free(semaphore); free(nom_absolu); @@ -693,7 +790,7 @@ sem_t } argument.val = valeur; - semctl((*semaphore), 0, SETVAL, argument); + semctl((*semaphore).sem, 0, SETVAL, argument); # else @@ -754,16 +851,20 @@ sem_t # endif } - free(nom_absolu); - 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); @@ -811,12 +912,9 @@ sem_close_SysV(sem_t *semaphore) int sem_unlink_SysV(const char *nom) { + // Détruit un sémaphore nommé créé par sem_open_SysV() # ifndef OS2 - sem_t semaphore; - - struct sembuf commande; - unsigned char *nom_absolu; if ((nom_absolu = malloc((strlen(chemin_semaphores_SysV) + strlen(nom) @@ -826,28 +924,7 @@ sem_unlink_SysV(const char *nom) } sprintf(nom_absolu, "%s%s", chemin_semaphores_SysV, nom); - - if ((semaphore = semget(ftok(nom_absolu, 1), 0, 0)) == -1) - { - free(nom_absolu); - return(EINVAL); - } - - commande.sem_num = 0; - commande.sem_op = 0; - commande.sem_flg = 0; - - if (semop(semaphore, &commande, 1) == -1) - { - free(nom_absolu); - return(EINVAL); - } - - if (semctl(semaphore, IPC_RMID, 0) == -1) - { - free(nom_absolu); - return(EINVAL); - } + semctl(semget(ftok(nom_absolu, 1), 0, 0), 0, IPC_RMID); if (unlink(nom_absolu) == -1) {