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