source: git/Singular/links/semaphore.c @ a3f0fea

spielwiese
Last change on this file since a3f0fea was a3f0fea, checked in by Reimer Behrends <behrends@…>, 5 years ago
Modify variable declarions for pSingular.
  • Property mode set to 100644
File size: 4.3 KB
Line 
1#include "kernel/mod2.h"
2
3#ifdef HAVE_SIMPLEIPC
4#include <semaphore.h>
5#include <fcntl.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <sys/types.h>
11#include <unistd.h>
12
13# include "simpleipc.h"
14
15#include "Singular/cntrlc.h"
16#include "reporter/si_signals.h"
17
18
19
20// Not yet implemented: SYSV IPC Semaphores
21// They are more difficult to clean up after a process crash
22// but are supported more widely.
23
24VAR sipc_sem_t *semaphore[SIPC_MAX_SEMAPHORES];
25VAR int sem_acquired[SIPC_MAX_SEMAPHORES];
26
27/* return 1 on success,
28 *        0 if already initialized,
29 *       -1 for errors
30 */
31int sipc_semaphore_init(int id, int count)
32{
33  char buf[100];
34  sipc_sem_t *sem;
35  if ((id<0) || (id >= SIPC_MAX_SEMAPHORES))
36    return -1;
37  // Already initialized?
38  if (semaphore[id])
39    return 0;
40  // to make it completely safe, we should generate a name
41  // from /dev/urandom.
42#if USE_SEM_INIT
43  // TODO: This should really use mapped memory so that processes
44  // can keep using the semaphore after fork + exec.
45  sem = malloc(sizeof(sem_t));
46  if (!sem)
47    return -1;
48  if (sem_init(sem, 1, count) < 0)
49  {
50    free(sem);
51    return -1;
52  }
53#else
54#if PORTABLE_SEMAPHORES
55#ifndef MAP_ANONYMOUS
56#define MAP_ANONYMOUS MAP_ANON
57#endif
58  sem = mmap(NULL, getpagesize(),
59    PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, -1, 0);
60  if (sem == MAP_FAILED)
61    return -1;
62  sem->count = count;
63  sprintf(buf, "/%d:sem%d:g", getpid(), id);
64  sem_unlink(buf);
65  sem->guard = sem_open(buf, O_CREAT, 0600, count);
66  sem_unlink(buf);
67  sprintf(buf, "/%d:sem%d:s", getpid(), id);
68  sem_unlink(buf);
69  sem->sig = sem_open(buf, O_CREAT, 0600, count);
70  sem_unlink(buf);
71#else
72  sprintf(buf, "/%d:sem%d", getpid(), id);
73  sem_unlink(buf);
74  sem = sem_open(buf, O_CREAT, 0600, count);
75#endif
76#endif
77#if !PORTABLE_SEMAPHORES
78  if (sem == SEM_FAILED || !sem)
79    return -1;
80#endif
81  semaphore[id] = sem;
82#if !USE_SEM_INIT
83  sem_unlink(buf);
84#endif
85  return 1;
86}
87
88int sipc_semaphore_exists(int id)
89{
90  if ((id<0) || (id >= SIPC_MAX_SEMAPHORES))  return -1;
91  return semaphore[id] != NULL;
92}
93
94int sipc_semaphore_acquire(int id)
95{
96  if ((id<0) || (id >= SIPC_MAX_SEMAPHORES) || (semaphore[id]==NULL))  return -1;
97  defer_shutdown++;
98#if PORTABLE_SEMAPHORES
99  si_sem_wait(semaphore[id]->sig);
100  si_sem_wait(semaphore[id]->guard);
101  semaphore[id]->count--;
102  sem_post(semaphore[id]->guard);
103#else
104  si_sem_wait(semaphore[id]);
105#endif
106  sem_acquired[id]++;
107  defer_shutdown--;
108  if (!defer_shutdown && do_shutdown) m2_end(1);
109  return 1;
110}
111
112int sipc_semaphore_try_acquire(int id)
113{
114  if ((id<0) || (id >= SIPC_MAX_SEMAPHORES) || (semaphore[id]==NULL))  return -1;
115  defer_shutdown++;
116#if PORTABLE_SEMAPHORES
117  int trywait = si_sem_trywait(semaphore[id]->sig);
118#else
119  int trywait = si_sem_trywait(semaphore[id]);
120#endif
121  if (!trywait)
122  {
123#if PORTABLE_SEMAPHORES
124    si_sem_wait(semaphore[id]->guard);
125    semaphore[id]->count--;
126    sem_post(semaphore[id]->guard);
127#endif
128    sem_acquired[id]++;
129  }
130  defer_shutdown--;
131  if (!defer_shutdown && do_shutdown) m2_end(1);
132  return !trywait;
133}
134
135int sipc_semaphore_release(int id)
136{
137  if ((id<0) || (id >= SIPC_MAX_SEMAPHORES) || (semaphore[id]==NULL))  return -1;
138  defer_shutdown++;
139#if PORTABLE_SEMAPHORES
140  sem_wait(semaphore[id]->guard);
141  semaphore[id]->count++;
142  sem_post(semaphore[id]->sig);
143  sem_post(semaphore[id]->guard);
144#else
145  sem_post(semaphore[id]);
146#endif
147  sem_acquired[id]--;
148  defer_shutdown--;
149  if (!defer_shutdown && do_shutdown) m2_end(1);
150  return 1;
151}
152
153int sipc_semaphore_get_value(int id)
154{
155  int val;
156  if ((id<0) || (id >= SIPC_MAX_SEMAPHORES) || (semaphore[id]==NULL))  return -1;
157#if PORTABLE_SEMAPHORES
158  sem_wait(semaphore[id]->guard);
159  val = semaphore[id]->count;
160  sem_post(semaphore[id]->guard);
161#else
162  sem_getvalue(semaphore[id], &val);
163#endif
164  return val;
165}
166
167int simpleipc_cmd(char *cmd, int id, int v)
168{
169  if (strcmp(cmd,"init")==0)
170    return sipc_semaphore_init(id,v);
171  else if (strcmp(cmd,"exists")==0)
172    return sipc_semaphore_exists(id);
173  else if (strcmp(cmd,"acquire")==0)
174    return  sipc_semaphore_acquire(id);
175  else if (strcmp(cmd,"try_acquire")==0)
176    return sipc_semaphore_try_acquire(id);
177  else if (strcmp(cmd,"release")==0)
178    return sipc_semaphore_release(id);
179  else if (strcmp(cmd,"get_value")==0)
180    return sipc_semaphore_get_value(id);
181  else printf("unknown\n");
182    return  -2;
183}
184#endif
Note: See TracBrowser for help on using the repository browser.