My Project
semaphore.c
Go to the documentation of this file.
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 
26 
27 /* return 1 on success,
28  * 0 if already initialized,
29  * -1 for errors
30  */
31 int 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 
89 {
90  if ((id<0) || (id >= SIPC_MAX_SEMAPHORES)) return -1;
91  return semaphore[id] != NULL;
92 }
93 
95 {
96  if ((id<0) || (id >= SIPC_MAX_SEMAPHORES) || (semaphore[id]==NULL)) return -1;
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 
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 
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 
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 
167 int 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
VAR volatile BOOLEAN do_shutdown
Definition: cntrlc.cc:82
VAR volatile int defer_shutdown
Definition: cntrlc.cc:83
const Variable & v
< [in] a sqrfree bivariate poly
Definition: facBivar.h:39
#define VAR
Definition: globaldefs.h:5
void m2_end(int i)
Definition: misc_ip.cc:1098
#define free
Definition: omAllocFunc.c:14
#define NULL
Definition: omList.c:12
void * malloc(size_t size)
Definition: omalloc.c:92
int sipc_semaphore_get_value(int id)
Definition: semaphore.c:153
int sipc_semaphore_acquire(int id)
Definition: semaphore.c:94
VAR sipc_sem_t * semaphore[SIPC_MAX_SEMAPHORES]
Definition: semaphore.c:24
VAR int sem_acquired[SIPC_MAX_SEMAPHORES]
Definition: semaphore.c:25
int sipc_semaphore_release(int id)
Definition: semaphore.c:135
int simpleipc_cmd(char *cmd, int id, int v)
Definition: semaphore.c:167
int sipc_semaphore_exists(int id)
Definition: semaphore.c:88
int sipc_semaphore_try_acquire(int id)
Definition: semaphore.c:112
int sipc_semaphore_init(int id, int count)
Definition: semaphore.c:31
int status int void size_t count
Definition: si_signals.h:59
int status int void * buf
Definition: si_signals.h:59
#define SIPC_MAX_SEMAPHORES
Definition: simpleipc.h:10
sem_t sipc_sem_t
Definition: simpleipc.h:27