1
# All lines beginning with `# DP:' are a description of the patch.
2
# DP: Description: Implement SysV shared memory for GNU/Hurd.
3
# DP: Dpatch author: Michael Banck <mbanck@debian.org>
4
# DP: Patch author: Marcus Brinkmann
5
# DP: Upstream status: Unsubmitted, copyright assignments needed
8
2005-07-11 Marcus Brinkmann <marcus@gnu.org>
10
* hurd/Makefile (routines): Add sysvshm.
11
(distribute): Add sysvshm.h.
12
* hurd/sysvshm.h: New file.
13
* hurd/sysvshm.c: New file.
14
* sysdeps/mach/hurd/bits/stat.h (S_IMMAP0): New macro.
15
(S_ISPARE): Unset the S_IMMAP0 flag.
16
* sysdeps/mach/hurd/ftok.c: New file.
17
* sysdeps/mach/hurd/shmat.c: New file.
18
* sysdeps/mach/hurd/shmctl.c: New file.
19
* sysdeps/mach/hurd/shmdt.c: New file.
20
* sysdeps/mach/hurd/bits/posix_opt.h: Define _XOPEN_SHM to 1.
24
hurd/sysvshm.c | 96 ++++++++++++++
25
hurd/sysvshm.h | 47 +++++++
26
sysdeps/mach/hurd/bits/posix_opt.h | 4
27
sysdeps/mach/hurd/ftok.c | 43 ++++++
28
sysdeps/mach/hurd/shmat.c | 78 +++++++++++
29
sysdeps/mach/hurd/shmctl.c | 132 +++++++++++++++++++
30
sysdeps/mach/hurd/shmdt.c | 51 +++++++
31
sysdeps/mach/hurd/shmget.c | 245 +++++++++++++++++++++++++++++++++++++
32
9 files changed, 696 insertions(+), 3 deletions(-)
38
ports-get ports-set hurdports hurdmsg \
41
$(sig) $(dtable) $(inlines) port-cleanup report-wait xattr
42
sig = hurdsig hurdfault siginfo hurd-raise preempt-sig \
43
trampoline longjmp-ts catch-exc exc2signal hurdkill sigunwind \
46
fd-close fd-read fd-write hurdioctl ctty-input ctty-output
47
inlines = $(inline-headers:%.h=%-inlines)
48
-distribute = hurdstartup.h hurdfault.h hurdhost.h \
49
+distribute = hurdstartup.h hurdfault.h hurdhost.h sysvshm.h \
50
faultexc.defs intr-rpc.defs intr-rpc.h intr-msg.h Notes
52
# XXX this is a temporary hack; see hurdmalloc.h
56
+/* Copyright (C) 2005 Free Software Foundation, Inc.
57
+ This file is part of the GNU C Library.
59
+ The GNU C Library is free software; you can redistribute it and/or
60
+ modify it under the terms of the GNU Lesser General Public
61
+ License as published by the Free Software Foundation; either
62
+ version 2.1 of the License, or (at your option) any later version.
64
+ The GNU C Library is distributed in the hope that it will be useful,
65
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
66
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
67
+ Lesser General Public License for more details.
69
+ You should have received a copy of the GNU Lesser General Public
70
+ License along with the GNU C Library; if not, write to the Free
71
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
82
+#include <sys/stat.h>
86
+/* Description of an shm attachment. */
87
+struct sysvshm_attach
90
+ struct sysvshm_attach *next;
99
+/* List of attachments. */
100
+static struct sysvshm_attach *attach_list;
102
+/* A lock to protect the linked list of shared memory attachments. */
103
+static struct mutex sysvshm_lock = MUTEX_INITIALIZER;
106
+/* Adds a segment attachment. */
108
+__sysvshm_add (void *addr, size_t size)
110
+ struct sysvshm_attach *shm;
112
+ shm = malloc (sizeof (*shm));
116
+ __mutex_lock (&sysvshm_lock);
119
+ shm->next = attach_list;
121
+ __mutex_unlock (&sysvshm_lock);
126
+/* Removes a segment attachment. Returns its size if found, or EINVAL
129
+__sysvshm_remove (void *addr, size_t *size)
131
+ struct sysvshm_attach *shm;
132
+ struct sysvshm_attach **pshm = &attach_list;
134
+ __mutex_lock (&sysvshm_lock);
139
+ if (shm->addr == addr)
143
+ __mutex_unlock (&sysvshm_lock);
149
+ __mutex_unlock (&sysvshm_lock);
155
+/* Copyright (C) 2005 Free Software Foundation, Inc.
156
+ This file is part of the GNU C Library.
158
+ The GNU C Library is free software; you can redistribute it and/or
159
+ modify it under the terms of the GNU Lesser General Public
160
+ License as published by the Free Software Foundation; either
161
+ version 2.1 of the License, or (at your option) any later version.
163
+ The GNU C Library is distributed in the hope that it will be useful,
164
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
165
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
166
+ Lesser General Public License for more details.
168
+ You should have received a copy of the GNU Lesser General Public
169
+ License along with the GNU C Library; if not, write to the Free
170
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
176
+/* The area (from top to bottom) that is used for private keys. These
177
+ are all keys that have the second highest bit set. */
178
+#define SHM_PRIV_KEY_START INT_MAX
179
+#define SHM_PRIV_KEY_END ((INT_MAX / 2) + 1)
181
+#define SHM_PREFIX "shm-"
182
+#define SHM_DIR _PATH_DEV "shm/"
184
+/* The maximum number of characters in a shared memory segment file name.
185
+ 32 is the max number of characters in a 128 bit number in hex. */
186
+#if __WORDSIZE > 128
187
+#error Need to increase SHM_NAMEMAX.
189
+#define SHM_NAMEMAX (sizeof (SHM_PREFIX) - 1 + 32 + 1)
192
+/* Use this with printf and its variants. */
193
+#define SHM_NAMEPRI SHM_PREFIX "%0x"
196
+/* Adds a segment attachment. */
197
+error_t __sysvshm_add (void *addr, size_t size);
199
+/* Removes a segment attachment. Returns its size if found, or EINVAL
201
+error_t __sysvshm_remove (void *addr, size_t *size);
203
+++ b/sysdeps/mach/hurd/ftok.c
205
+/* Copyright (C) 1995, 1996, 2000, 2005 Free Software Foundation, Inc.
206
+ This file is part of the GNU C Library.
207
+ Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
209
+ The GNU C Library is free software; you can redistribute it and/or
210
+ modify it under the terms of the GNU Lesser General Public
211
+ License as published by the Free Software Foundation; either
212
+ version 2.1 of the License, or (at your option) any later version.
214
+ The GNU C Library is distributed in the hope that it will be useful,
215
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
216
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
217
+ Lesser General Public License for more details.
219
+ You should have received a copy of the GNU Lesser General Public
220
+ License along with the GNU C Library; if not, write to the Free
221
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
224
+#include <sys/ipc.h>
225
+#include <sys/stat.h>
228
+/* In the Hurd, we use the second-to-most-significant bit as flag for
229
+ private keys. We use a different order of the components so that
230
+ the biggest one---the inode number---is affected by this. */
233
+ftok (pathname, proj_id)
234
+ const char *pathname;
240
+ if (__xstat64 (_STAT_VER, pathname, &st) < 0)
243
+ key = ((st.st_dev & 0xff) | ((proj_id & 0xff) << 8)
244
+ | ((st.st_ino & 0x3fff) << 16));
249
+++ b/sysdeps/mach/hurd/shmat.c
251
+/* Copyright (C) 2005 Free Software Foundation, Inc.
252
+ This file is part of the GNU C Library.
254
+ The GNU C Library is free software; you can redistribute it and/or
255
+ modify it under the terms of the GNU Lesser General Public
256
+ License as published by the Free Software Foundation; either
257
+ version 2.1 of the License, or (at your option) any later version.
259
+ The GNU C Library is distributed in the hope that it will be useful,
260
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
261
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
262
+ Lesser General Public License for more details.
264
+ You should have received a copy of the GNU Lesser General Public
265
+ License along with the GNU C Library; if not, write to the Free
266
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
273
+#include <sys/mman.h>
274
+#include <sys/ipc.h>
275
+#include <sys/shm.h>
276
+#include <sys/time.h>
277
+#include <sys/stat.h>
280
+#include "sysvshm.h"
282
+/* Attach the shared memory segment associated with SHMID to the data
283
+ segment of the calling process. SHMADDR and SHMFLG determine how
284
+ and where the segment is attached. */
286
+__shmat (int shmid, const void *shmaddr, int shmflg)
289
+ char filename[sizeof (SHM_DIR) - 1 + SHM_NAMEMAX];
292
+ struct stat statbuf;
295
+ sprintf (filename, SHM_DIR SHM_NAMEPRI, shmid);
296
+ fd = __open (filename, (shmflg & SHM_RDONLY) ? O_RDONLY : O_RDWR);
299
+ if (errno == ENOENT)
301
+ return (void *) -1;
304
+ res = __fstat (fd, &statbuf);
308
+ return (void *) -1;
311
+ addr = __mmap ((void *) shmaddr, statbuf.st_size,
312
+ PROT_READ | ((shmflg & SHM_RDONLY) ? 0 : PROT_WRITE),
313
+ MAP_SHARED, fd, 0);
315
+ if (addr == MAP_FAILED)
316
+ return (void *) -1;
318
+ err = __sysvshm_add (addr, statbuf.st_size);
321
+ munmap (addr, statbuf.st_size);
322
+ return (void *) -1;
328
+weak_alias(__shmat, shmat)
330
+++ b/sysdeps/mach/hurd/shmctl.c
332
+/* Copyright (C) 2005 Free Software Foundation, Inc.
333
+ This file is part of the GNU C Library.
335
+ The GNU C Library is free software; you can redistribute it and/or
336
+ modify it under the terms of the GNU Lesser General Public
337
+ License as published by the Free Software Foundation; either
338
+ version 2.1 of the License, or (at your option) any later version.
340
+ The GNU C Library is distributed in the hope that it will be useful,
341
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
342
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
343
+ Lesser General Public License for more details.
345
+ You should have received a copy of the GNU Lesser General Public
346
+ License along with the GNU C Library; if not, write to the Free
347
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
353
+#include <sys/mman.h>
354
+#include <sys/ipc.h>
355
+#include <sys/shm.h>
356
+#include <sys/stat.h>
359
+#include "sysvshm.h"
361
+/* Provide operations to control over shared memory segments. */
363
+__shmctl (int id, int cmd, struct shmid_ds *buf)
368
+ char filename[sizeof (SHM_DIR) - 1 + SHM_NAMEMAX];
369
+ struct stat statbuf;
371
+ sprintf (filename, SHM_DIR SHM_NAMEPRI, id);
372
+ /* SysV requires read access for IPC_STAT. */
373
+ fd = __open (filename, O_NORW);
376
+ if (errno == ENOENT)
381
+ res = __fstat (fd, &statbuf);
394
+ buf->shm_perm.__key = id;
395
+ buf->shm_perm.uid = statbuf.st_uid;
396
+ buf->shm_perm.gid = statbuf.st_gid;
398
+ /* We do not support the creator. */
399
+ buf->shm_perm.cuid = statbuf.st_uid;
400
+ buf->shm_perm.cgid = statbuf.st_gid;
402
+ /* We just want the protection bits. */
403
+ buf->shm_perm.mode = statbuf.st_mode & 0777;
404
+ /* Hopeless. We do not support a sequence number. */
405
+ buf->shm_perm.__seq = statbuf.st_ino;
406
+ buf->shm_segsz = statbuf.st_size;
408
+ /* Hopeless. We do not support any of these. */
409
+ buf->shm_atime = statbuf.st_atime;
410
+ buf->shm_dtime = statbuf.st_mtime;
411
+ /* Well, this comes at least close. */
412
+ buf->shm_ctime = statbuf.st_ctime;
414
+ /* We do not support the PID. */
418
+ if (statbuf.st_mode & S_IMMAP0)
419
+ buf->shm_nattch = 0;
421
+ /* 42 is the answer. Of course this is bogus, but for most
422
+ applications, this should be fine. */
423
+ buf->shm_nattch = 42;
428
+ if (statbuf.st_uid != buf->shm_perm.uid
429
+ || statbuf.st_gid != buf->shm_perm.gid)
431
+ res = __fchown (fd,
432
+ (statbuf.st_uid != buf->shm_perm.uid)
433
+ ? buf->shm_perm.uid : -1,
434
+ (statbuf.st_gid != buf->shm_perm.gid)
435
+ ? buf->shm_perm.gid : -1);
440
+ if (!err && statbuf.st_mode & 0777 != buf->shm_perm.mode & 0777)
442
+ res = __fchmod (fd, (statbuf.st_mode & ~0777)
443
+ | (buf->shm_perm.mode & 0777));
450
+ res = __unlink (filename);
451
+ /* FIXME: Check error (mapping ENOENT to EINVAL). */
460
+ return err ? -1 : 0;
463
+weak_alias(__shmctl, shmctl)
465
+++ b/sysdeps/mach/hurd/shmdt.c
467
+/* Copyright (C) 2005 Free Software Foundation, Inc.
468
+ This file is part of the GNU C Library.
470
+ The GNU C Library is free software; you can redistribute it and/or
471
+ modify it under the terms of the GNU Lesser General Public
472
+ License as published by the Free Software Foundation; either
473
+ version 2.1 of the License, or (at your option) any later version.
475
+ The GNU C Library is distributed in the hope that it will be useful,
476
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
477
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
478
+ Lesser General Public License for more details.
480
+ You should have received a copy of the GNU Lesser General Public
481
+ License along with the GNU C Library; if not, write to the Free
482
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
490
+#include <sys/mman.h>
491
+#include <sys/ipc.h>
492
+#include <sys/shm.h>
493
+#include <sys/time.h>
494
+#include <sys/stat.h>
496
+#include "sysvshm.h"
498
+/* Detach shared memory segment starting at address specified by
499
+ SHMADDR from the caller's data segment. */
501
+__shmdt (const void *shmaddr)
506
+ err = __sysvshm_remove ((void *) shmaddr, &size);
513
+ __munmap ((void *) shmaddr, size);
517
+weak_alias(__shmdt, shmdt)
519
+++ b/sysdeps/mach/hurd/shmget.c
521
+/* Copyright (C) 2005 Free Software Foundation, Inc.
522
+ This file is part of the GNU C Library.
524
+ The GNU C Library is free software; you can redistribute it and/or
525
+ modify it under the terms of the GNU Lesser General Public
526
+ License as published by the Free Software Foundation; either
527
+ version 2.1 of the License, or (at your option) any later version.
529
+ The GNU C Library is distributed in the hope that it will be useful,
530
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
531
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
532
+ Lesser General Public License for more details.
534
+ You should have received a copy of the GNU Lesser General Public
535
+ License along with the GNU C Library; if not, write to the Free
536
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
539
+#include <stdbool.h>
542
+#include <sys/shm.h>
543
+#include <sys/types.h>
544
+#include <sys/stat.h>
550
+#include <hurd/fd.h>
552
+#include "sysvshm.h"
554
+/* Create a new shared memory segment file without linking it into the
555
+ filesystem. Return the directory and file ports in R_DIR and R_FILE. */
557
+create_shm_file (size_t size, int flags, file_t *r_dir, file_t *r_file)
565
+ /* Get a port to the directory that will contain the file. */
566
+ dir = __file_name_lookup (SHM_DIR, 0, 0);
567
+ if (dir == MACH_PORT_NULL)
570
+ /* Create an unnamed file in the directory. */
571
+ err = __dir_mkfile (dir, O_RDWR, flags, &file);
574
+ __mach_port_deallocate (__mach_task_self (), dir);
578
+ err = __file_set_size (file, size);
581
+ __mach_port_deallocate (__mach_task_self (), file);
582
+ __mach_port_deallocate (__mach_task_self (), dir);
594
+/* Open the shared memory segment *R_KEY and return a file descriptor
595
+ to it in R_FD. If KEY is IPC_PRIVATE, use a private key and return
598
+get_exclusive (int shmflags, size_t size, key_t *r_key, int *r_fd)
603
+ char filename[SHM_NAMEMAX];
604
+ key_t key = *r_key;
607
+ /* Create the shared memory segment. */
608
+ err = create_shm_file (size, shmflags, &dir, &file);
612
+ if (key == IPC_PRIVATE)
615
+ key = SHM_PRIV_KEY_START;
617
+ /* Try to link the shared memory segment into the filesystem
618
+ (exclusively). Private segments have negative keys. */
621
+ sprintf (filename, SHM_NAMEPRI, key);
622
+ err = __dir_link (dir, file, filename, 1);
629
+ else if (err == EEXIST)
631
+ /* Check if we ran out of keys. If not, try again with new
633
+ if (key == SHM_PRIV_KEY_END)
645
+ /* Try to link the shared memory segment into the filesystem
646
+ (exclusively) under the given key. */
647
+ sprintf (filename, SHM_NAMEPRI, key);
648
+ err = __dir_link (dir, file, filename, 1);
651
+ __mach_port_deallocate (__mach_task_self (), dir);
657
+ /* Get a file descriptor for that port. */
658
+ fd = _hurd_intern_fd (file, O_RDWR, 1); /* dealloc on error */
669
+/* Open the shared memory segment KEY (creating it if it doesn't yet
670
+ exist) and return a file descriptor to it in R_FD. */
672
+get_shared (int shmflags, size_t size, key_t key, int *r_fd)
675
+ char filename[sizeof (SHM_DIR) - 1 + SHM_NAMEMAX];
677
+ sprintf (filename, SHM_DIR SHM_NAMEPRI, key);
681
+ fd = __open (filename, O_NORW, shmflags & 0777);
683
+ if (fd < 0 && errno != ENOENT)
689
+ struct stat statbuf;
691
+ /* Check the size (we only need to do this if we did not
692
+ create the shared memory segment file ourselves). */
693
+ res = __fstat (fd, &statbuf);
701
+ if (statbuf.st_size < size)
709
+ /* The memory segment doesn't exist. */
710
+ if (shmflags & IPC_CREAT)
712
+ /* Try to create it exclusively. */
713
+ err = get_exclusive (shmflags, size, &key, &fd);
715
+ /* If somebody created it in the meanwhile, just try again. */
722
+ while (fd < 0 && !err);
732
+/* Return an identifier for an shared memory segment of at least size
733
+ SIZE which is associated with KEY. */
735
+__shmget (key_t key, size_t size, int shmflags)
740
+ if (key == IPC_PRIVATE || shmflags & IPC_EXCL)
741
+ /* An exclusive shared memory segment must be created. */
742
+ err = get_exclusive (shmflags, size, &key, &fd);
744
+ err = get_shared (shmflags, size, key, &fd);
752
+ /* From here, we can't fail. That's important, as otherwise we
753
+ would need to unlink the file if we created it (in that case, the
754
+ code above would have to be changed to pass a "created" flag down
762
+weak_alias(__shmget, shmget)
763
--- a/sysdeps/mach/hurd/bits/posix_opt.h
764
+++ b/sysdeps/mach/hurd/bits/posix_opt.h
766
/* X/Open thread realtime support is not supported. */
767
#undef _XOPEN_REALTIME_THREADS
769
-/* XPG4.2 shared memory is not supported. */
771
+/* XPG4.2 shared memory is supported. */
772
+#define _XOPEN_SHM 1
774
/* We do not have the POSIX threads interface. */
775
#define _POSIX_THREADS -1