Skip to content

Commit 609bbd1

Browse files
committed
Experimental implementation of sem_open/sem_close/sem_unlink
1 parent 55e6699 commit 609bbd1

15 files changed

+417
-41
lines changed

posix/SRCFILES

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ SRCFILES = \
3636
sem_trywait.c \
3737
sem_wait.c \
3838
sem_waitcommon.c \
39+
sem_open.c \
40+
sem_close.c \
41+
sem_unlink.c \
42+
shm-directory.c \
3943
sleep.c \
4044
sysconf.c \
4145
system.c \

posix/sem_clockwait.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include <time.h>
55
#include "semaphoreP.h"
66

7+
/* Adapted to MiNTLib by Thorsten Otto */
8+
79
int sem_clockwait(sem_t *sem, clockid_t clockid, const struct timespec *abstime)
810
{
911
long ret;

posix/sem_close.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/* Copyright (C) 2002-2023 Free Software Foundation, Inc.
2+
This file is part of the GNU C Library.
3+
4+
The GNU C Library is free software; you can redistribute it and/or
5+
modify it under the terms of the GNU Lesser General Public
6+
License as published by the Free Software Foundation; either
7+
version 2.1 of the License, or (at your option) any later version.
8+
9+
The GNU C Library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with the GNU C Library; if not, see
16+
<https://www.gnu.org/licenses/>. */
17+
18+
/* Adapted to MiNTLib by Thorsten Otto */
19+
20+
#include <stdlib.h>
21+
#include <errno.h>
22+
#include <mint/mintbind.h>
23+
#include "semaphoreP.h"
24+
25+
26+
int sem_close(sem_t *sem_ptr)
27+
{
28+
/*
29+
if (sem_ptr == SEM_FAILED)
30+
{
31+
__set_errno(EINVAL);
32+
return -1;
33+
}
34+
*/
35+
36+
Mfree(sem_ptr);
37+
38+
return 0;
39+
}

posix/sem_destroy.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
#include <stdlib.h>
2-
#include <mint/mintbind.h>
3-
#include <errno.h>
4-
#include "semaphoreP.h"
5-
61
/*
72
* M.Medour 2023/05/24
83
* rev.1
94
* semaphore.h for freemint
105
*/
116

7+
/* Adapted to MiNTLib by Thorsten Otto */
8+
9+
#include <stdlib.h>
10+
#include <mint/mintbind.h>
11+
#include <errno.h>
12+
#include "semaphoreP.h"
13+
1214
/* We're done with the semaphore, destroy it. */
1315
int sem_destroy(sem_t *sem)
1416
{

posix/sem_getvalue.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
#include <stdlib.h>
2-
#include <mint/mintbind.h>
3-
#include <errno.h>
4-
#include "semaphoreP.h"
5-
61
/*
72
* M.Medour 2023/05/24
83
* rev.1
94
* semaphore.h for freemint
105
*/
116

7+
/* Adapted to MiNTLib by Thorsten Otto */
8+
9+
#include <stdlib.h>
10+
#include <mint/mintbind.h>
11+
#include <errno.h>
12+
#include "semaphoreP.h"
13+
1214
/* Get the semaphore value. */
1315
int sem_getvalue(sem_t *sem, int *sval)
1416
{

posix/sem_init.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
#include <stdlib.h>
2-
#include <mint/mintbind.h>
3-
#include <errno.h>
4-
#include "semaphoreP.h"
5-
61
/*
72
* M.Medour 2023/05/24
83
* rev.1
94
* semaphore.h for freemint
105
*/
116

7+
/* Adapted to MiNTLib by Thorsten Otto */
8+
9+
#include <stdlib.h>
10+
#include <mint/mintbind.h>
11+
#include <errno.h>
12+
#include "semaphoreP.h"
13+
1214
static long gen_sem_id(void)
1315
{
1416
int n;

posix/sem_open.c

Lines changed: 201 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,216 @@
1616
License along with the GNU C Library; if not, see
1717
<https://www.gnu.org/licenses/>. */
1818

19+
/* Adapted to MiNTLib by Thorsten Otto */
20+
1921
#include <stdlib.h>
2022
#include <mint/mintbind.h>
2123
#include <errno.h>
22-
#include <time.h>
24+
#include <stdarg.h>
25+
#include <string.h>
26+
#include <fcntl.h>
27+
#include <sys/ioctl.h>
28+
#include <unistd.h>
2329
#include "semaphoreP.h"
2430

25-
static inline void __sem_open_init(struct new_sem *sem, unsigned value)
31+
32+
static inline void __sem_open_init(sem_t *sem, const char *name, unsigned int value)
2633
{
34+
int i;
35+
2736
sem->value = value << SEM_VALUE_SHIFT;
2837
sem->nwaiters = 0;
2938

3039
/* This always is a shared semaphore. */
3140
sem->__private = 1;
41+
sem->sem_id = 0;
42+
for (i = 0; i < SEM_NAME_MAX && *name; i++)
43+
{
44+
sem->sem_id <<= 8;
45+
sem->sem_id |= (unsigned char)*name;
46+
name++;
47+
}
48+
for (; i < SEM_NAME_MAX; i++)
49+
sem->sem_id <<= 8;
50+
}
51+
52+
53+
sem_t *sem_open(const char *name, int oflag, ...)
54+
{
55+
struct shmdir_name dirname;
56+
sem_t *result;
57+
int fd;
58+
#ifdef HAVE_PTHREAD_H
59+
int state;
60+
#endif
61+
int ret;
62+
63+
if (__shm_get_name(&dirname, name, 1) != 0)
64+
{
65+
return SEM_FAILED;
66+
}
67+
68+
/* Disable asynchronous cancellation. */
69+
#ifdef HAVE_PTHREAD_H
70+
__pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
71+
#endif
72+
73+
/* If the semaphore object has to exist simply open it. */
74+
if ((oflag & O_CREAT) == 0 || (oflag & O_EXCL) == 0)
75+
{
76+
try_again:
77+
fd = __open(dirname.name, (oflag & ~(O_CREAT | O_ACCMODE)) | O_NOFOLLOW | O_RDWR);
78+
79+
if (fd == -1)
80+
{
81+
/* If we are supposed to create the file try this next. */
82+
if ((oflag & O_CREAT) != 0 && errno == ENOENT)
83+
goto try_create;
84+
85+
/* Return. errno is already set. */
86+
} else
87+
{
88+
/* Check whether we already have this semaphore mapped and
89+
create one if necessary. */
90+
result = (sem_t *) Fcntl(fd, 0, SHMGETBLK);
91+
}
92+
} else
93+
{
94+
/* We have to open a temporary file first since it must have the
95+
correct form before we can start using it. */
96+
mode_t mode;
97+
unsigned int value;
98+
va_list ap;
99+
char tmpfname[sizeof(SHMDIR) + 10] = SHMDIR "sem.XXXXXX";
100+
int retries;
101+
102+
try_create:
103+
va_start(ap, oflag);
104+
105+
mode = va_arg(ap, mode_t);
106+
value = va_arg(ap, unsigned int);
107+
108+
va_end(ap);
109+
110+
if (value > SEM_VALUE_MAX)
111+
{
112+
__set_errno(EINVAL);
113+
result = SEM_FAILED;
114+
goto out;
115+
}
116+
117+
/* Create the initial file content. */
118+
result = (sem_t *) Mxalloc(sizeof(sem_t), MX_PREFTTRAM | MX_GLOBAL);
119+
if (result == NULL)
120+
{
121+
__set_errno(ENOMEM);
122+
goto out;
123+
}
124+
125+
__sem_open_init(result, name, value);
126+
127+
retries = 0;
128+
129+
#define NRETRIES 50
130+
for (;;)
131+
{
132+
/* We really want to use mktemp here. We cannot use mkstemp
133+
since the file must be opened with a specific mode. The
134+
mode cannot later be set since then we cannot apply the
135+
file create mask. */
136+
if (mktemp(tmpfname) == NULL)
137+
{
138+
result = SEM_FAILED;
139+
goto out;
140+
}
141+
142+
/* Open the file. Make sure we do not overwrite anything. */
143+
fd = __open(tmpfname, O_RDWR | O_CREAT | O_EXCL, mode);
144+
if (fd == -1)
145+
{
146+
if (errno == EEXIST)
147+
{
148+
if (++retries < NRETRIES)
149+
{
150+
/* Restore the six placeholder bytes before the
151+
null terminator before the next attempt. */
152+
memcpy(tmpfname + sizeof(tmpfname) - 7, "XXXXXX", 6);
153+
continue;
154+
}
155+
156+
__set_errno(EAGAIN);
157+
}
158+
159+
result = SEM_FAILED;
160+
goto out;
161+
}
162+
163+
/* We got a file. */
164+
break;
165+
}
166+
167+
/* Map the sem_t structure from the file. */
168+
ret = Fcntl(fd, result, SHMSETBLK);
169+
if (ret == 0)
170+
{
171+
/* Create the file. Don't overwrite an existing file. */
172+
if (__link(tmpfname, dirname.name) != 0)
173+
{
174+
/* Undo the mapping. */
175+
Mfree(result);
176+
177+
/* Reinitialize 'result'. */
178+
result = SEM_FAILED;
179+
180+
/* This failed. If O_EXCL is not set and the problem was
181+
that the file exists, try again. */
182+
if ((oflag & O_EXCL) == 0 && errno == EEXIST)
183+
{
184+
/* Remove the file. */
185+
__unlink(tmpfname);
186+
187+
/* Close the file. */
188+
close(fd);
189+
190+
goto try_again;
191+
}
192+
} else
193+
{
194+
/* Insert the mapping into the search tree. This also
195+
determines whether another thread sneaked by and already
196+
added such a mapping despite the fact that we created it. */
197+
/* result = __sem_check_add_mapping(name, fd, result); */
198+
ret = Psemaphore(0, result->sem_id, 0);
199+
200+
if (ret != 0)
201+
{
202+
__set_errno(-ret);
203+
Mfree(result);
204+
result = SEM_FAILED;
205+
goto out;
206+
}
207+
}
208+
}
209+
210+
/* Now remove the temporary name. This should never fail. If
211+
it fails we leak a file name. Better fix the kernel. */
212+
__unlink(tmpfname);
213+
}
214+
215+
/* We don't need the file descriptor anymore. */
216+
if (fd != -1)
217+
{
218+
/* Do not disturb errno. */
219+
int save = errno;
220+
221+
__close(fd);
222+
errno = save;
223+
}
224+
225+
out:
226+
#ifdef HAVE_PTHREAD_H
227+
__pthread_setcancelstate(state, NULL);
228+
#endif
229+
230+
return result;
32231
}

posix/sem_post.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
#include <stdlib.h>
2-
#include <mint/mintbind.h>
3-
#include <errno.h>
4-
#include "semaphoreP.h"
5-
61
/*
72
* M.Medour 2023/05/24
83
* rev.1
94
* semaphore.h for freemint
105
*/
116

7+
/* Adapted to MiNTLib by Thorsten Otto */
8+
9+
#include <stdlib.h>
10+
#include <mint/mintbind.h>
11+
#include <errno.h>
12+
#include "semaphoreP.h"
13+
1214
/* See sem_wait for an explanation of the algorithm. */
1315
int sem_post(sem_t *sem)
1416
{

posix/sem_timedwait.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
#include <stdlib.h>
2-
#include <mint/mintbind.h>
3-
#include <errno.h>
4-
#include <time.h>
5-
#include "semaphoreP.h"
6-
71
/*
82
* M.Medour 2023/05/24
93
* rev.1
104
* semaphore.h for freemint
115
*/
126

7+
/* Adapted to MiNTLib by Thorsten Otto */
8+
9+
#include <stdlib.h>
10+
#include <mint/mintbind.h>
11+
#include <errno.h>
12+
#include <time.h>
13+
#include "semaphoreP.h"
14+
1315
/* This is in a separate file because because sem_timedwait is only provided
1416
if __USE_XOPEN2K is defined. */
1517
int sem_timedwait(sem_t *sem, const struct timespec *abstime)

0 commit comments

Comments
 (0)