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