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