--- rpl/src/semaphores.c 2010/08/06 15:33:04 1.7 +++ rpl/src/semaphores.c 2011/06/20 17:54:21 1.20 @@ -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.0.prerelease.1 + Copyright (C) 1989-2011 Dr. BERTRAND Joël This file is part of RPL/2. @@ -40,7 +40,7 @@ sem_t * sem_init2(unsigned int valeur, enum t_semaphore 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(), (int) semaphore); return(sem_open(noms_semaphores[semaphore], O_CREAT, @@ -107,7 +107,7 @@ sem_getvalue2(sem_t *semaphore, int *val #endif -#ifdef OS2 +#ifdef IPCS_SYSV /* ================================================================================ @@ -121,102 +121,336 @@ sem_getvalue2(sem_t *semaphore, int *val ================================================================================ */ -extern unsigned char *chemin_semaphores_SysV; +#ifndef OS2 + extern unsigned char *chemin_semaphores_SysV; +#else + unsigned char racine_semaphores_OS2[] = "\\SEM32\\"; + unsigned char racine_memoire_OS2[] = "\\SHAREMEM\\"; +#endif int -sem_init(sem_t *semaphore, int shared, unsigned int valeur) +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) { - return(ENOSYS); + errno = ENOSYS; + 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) { - return(EINVAL); + errno = EINVAL; + return(-1); } argument.val = valeur; - semctl((*semaphore), 0, SETVAL, argument); + 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(sem_t *semaphore) +sem_destroy_SysV(sem_t *semaphore) { - if (semctl((*semaphore), IPC_RMID, 0) == -1) + // 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(sem_t *semaphore) +sem_wait_SysV(sem_t *semaphore) { +# ifndef OS2 + struct sembuf commande; commande.sem_num = 0; commande.sem_op = -1; commande.sem_flg = 0; - if (semop((*semaphore), &commande, 1) == -1) + while(semop((*semaphore).sem, &commande, 1) == -1) { - return(EINVAL); + 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(sem_t *semaphore) +sem_trywait_SysV(sem_t *semaphore) { +# ifndef OS2 + struct sembuf commande; commande.sem_num = 0; commande.sem_op = -1; commande.sem_flg = IPC_NOWAIT; - if (semop((*semaphore), &commande, 1) == -1) + while(semop((*semaphore).sem, &commande, 1) == -1) { - if (errno == EAGAIN) + if (errno != EINTR) { - return(EAGAIN); + errno = EINVAL; + return(-1); } + } - return(EINVAL); + 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(sem_t *semaphore) +sem_post_SysV(sem_t *semaphore) { +# ifndef OS2 + struct sembuf commande; commande.sem_num = 0; commande.sem_op = 1; commande.sem_flg = 0; - if (semop((*semaphore), &commande, 1) == -1) + while(semop((*semaphore).sem, &commande, 1) == -1) { - return(EINVAL); + 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(sem_t *semaphore, int *valeur) +sem_getvalue_SysV(sem_t *semaphore, int *valeur) { - (*valeur) = semctl((*semaphore), 0, GETVAL); +# ifndef OS2 + + (*valeur) = semctl((*semaphore).sem, 0, GETVAL); if ((*valeur) < 0) { @@ -224,10 +458,29 @@ sem_getvalue(sem_t *semaphore, int *vale } 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(const char *nom, int oflag, ...) +*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) { @@ -235,7 +488,13 @@ sem_t sem_t *semaphore; +# ifndef OS2 + file *desc; + + key_t clef; + union semun argument; +# endif unsigned char *nom_absolu; @@ -243,6 +502,17 @@ sem_t 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) { @@ -256,18 +526,150 @@ sem_t 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 - (*semaphore) = semget(ftok(nom_absolu, 1), 0, 0); - if ((*semaphore) == -1) +# 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 { @@ -281,13 +683,34 @@ sem_t valeur = va_arg(liste, unsigned int); va_end(liste); - (*semaphore) = semget(ftok(nom_absolu, 1), 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); +# 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); + } - if ((*semaphore) == -1) + (*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); @@ -296,60 +719,142 @@ sem_t } argument.val = valeur; - semctl((*semaphore), 0, SETVAL, argument); - } + semctl((*semaphore).sem, 0, SETVAL, argument); - free(nom_absolu); +# else - return(SEM_FAILED); + 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(sem_t *semaphore) +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); -} -int -sem_unlink(const char *nom) -{ - sem_t semaphore; +# else - struct sembuf commande; + sem_t *psem; - unsigned char *nom_absolu; + psem = semaphore; - if ((nom_absolu = malloc((strlen(chemin_semaphores_SysV) + strlen(nom) - + 1) * sizeof(unsigned char))) == NULL) + if (DosCloseMutexSem((*psem).hmtx) != 0) { - return(ENOMEM); + return(EINVAL); } - sprintf(nom_absolu, "%s%s", chemin_semaphores_SysV, nom); - - if ((semaphore = semget(ftok(nom_absolu, 1), 0, 0)) == -1) - { - free(nom_absolu); - return(EINVAL); + while(DosCloseEventSem((*psem).hev) == ERROR_SEM_BUSY) + { + DosPostEventSem((*psem).hev); } - commande.sem_num = 0; - commande.sem_op = 0; - commande.sem_flg = 0; + (*(*psem).nopened)--; - if (semop(semaphore, &commande, 1) == -1) + if ((*psem).shared == 0) { - free(nom_absolu); - return(EINVAL); + free((*psem).cnt); + free((*psem).nopened); + } + else + { + if ((*(*psem).nopened) == 0) + { + DosFreeMem((*psem).cnt); + } } - if (semctl(semaphore, IPC_RMID, 0) == -1) + if ((*psem).allocated != 0) { - free(nom_absolu); - return(EINVAL); + 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); @@ -359,6 +864,12 @@ sem_unlink(const char *nom) free(nom_absolu); return(0); + +# else + + return(0); + +# endif } #endif