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