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