summaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/htl/pt-getspecific.c1
-rw-r--r--sysdeps/htl/pt-setspecific.c1
-rw-r--r--sysdeps/htl/pthreadP.h2
-rw-r--r--sysdeps/i386/atomic-machine.h107
-rw-r--r--sysdeps/mach/Makefile2
-rw-r--r--sysdeps/mach/hurd/Makefile4
-rw-r--r--sysdeps/mach/hurd/bind.c17
-rw-r--r--sysdeps/mach/hurd/bits/fcntl.h15
-rw-r--r--sysdeps/mach/hurd/bits/sigaction.h86
-rw-r--r--sysdeps/mach/hurd/brk.c6
-rw-r--r--sysdeps/mach/hurd/dl-sysdep.c28
-rw-r--r--sysdeps/mach/hurd/f_setlk.c68
-rw-r--r--sysdeps/mach/hurd/faccessat.c1
-rw-r--r--sysdeps/mach/hurd/fcntl.c57
-rw-r--r--sysdeps/mach/hurd/fork.c32
-rw-r--r--sysdeps/mach/hurd/getcwd.c12
-rw-r--r--sysdeps/mach/hurd/i386/bits/sigcontext.h4
-rw-r--r--sysdeps/mach/hurd/i386/exc2signal.c122
-rw-r--r--sysdeps/mach/hurd/i386/getcontext.S4
-rw-r--r--sysdeps/mach/hurd/i386/makecontext.S2
-rw-r--r--sysdeps/mach/hurd/i386/setcontext.S4
-rw-r--r--sysdeps/mach/hurd/i386/sigreturn.c68
-rw-r--r--sysdeps/mach/hurd/i386/swapcontext.S4
-rw-r--r--sysdeps/mach/hurd/i386/trampoline.c128
-rw-r--r--sysdeps/mach/hurd/ifaddrs.c310
-rw-r--r--sysdeps/mach/hurd/jmp-unwind.c3
-rw-r--r--sysdeps/mach/hurd/kill.c2
-rw-r--r--sysdeps/mach/hurd/msync.c93
-rw-r--r--sysdeps/mach/hurd/recvmsg.c234
-rw-r--r--sysdeps/mach/hurd/sendmsg.c109
-rw-r--r--sysdeps/mach/hurd/setegid.c1
-rw-r--r--sysdeps/mach/hurd/seteuid.c1
-rw-r--r--sysdeps/mach/hurd/setgid.c1
-rw-r--r--sysdeps/mach/hurd/setgroups.c1
-rw-r--r--sysdeps/mach/hurd/setitimer.c22
-rw-r--r--sysdeps/mach/hurd/setregid.c1
-rw-r--r--sysdeps/mach/hurd/setresgid.c1
-rw-r--r--sysdeps/mach/hurd/setresuid.c1
-rw-r--r--sysdeps/mach/hurd/setreuid.c1
-rw-r--r--sysdeps/mach/hurd/setsid.c1
-rw-r--r--sysdeps/mach/hurd/setuid.c1
-rw-r--r--sysdeps/mach/hurd/sigaction.c16
-rw-r--r--sysdeps/mach/hurd/sigpending.c6
-rw-r--r--sysdeps/mach/hurd/sigprocmask.c8
-rw-r--r--sysdeps/mach/hurd/sigsuspend.c15
-rw-r--r--sysdeps/mach/hurd/sigwait.c21
-rw-r--r--sysdeps/mach/hurd/spawni.c27
-rw-r--r--sysdeps/unix/bsd/unlockpt.c2
-rw-r--r--sysdeps/unix/clock_settime.c3
49 files changed, 1366 insertions, 290 deletions
diff --git a/sysdeps/htl/pt-getspecific.c b/sysdeps/htl/pt-getspecific.c
index a0227a67f6..64ddf9551a 100644
--- a/sysdeps/htl/pt-getspecific.c
+++ b/sysdeps/htl/pt-getspecific.c
@@ -36,3 +36,4 @@ __pthread_getspecific (pthread_key_t key)
return self->thread_specifics[key];
}
strong_alias (__pthread_getspecific, pthread_getspecific);
+hidden_def (__pthread_getspecific)
diff --git a/sysdeps/htl/pt-setspecific.c b/sysdeps/htl/pt-setspecific.c
index a46a12f157..02aff417ef 100644
--- a/sysdeps/htl/pt-setspecific.c
+++ b/sysdeps/htl/pt-setspecific.c
@@ -48,3 +48,4 @@ __pthread_setspecific (pthread_key_t key, const void *value)
return 0;
}
strong_alias (__pthread_setspecific, pthread_setspecific);
+hidden_def (__pthread_setspecific)
diff --git a/sysdeps/htl/pthreadP.h b/sysdeps/htl/pthreadP.h
index 132ac1718e..71c2fcd9c6 100644
--- a/sysdeps/htl/pthreadP.h
+++ b/sysdeps/htl/pthreadP.h
@@ -68,6 +68,8 @@ struct __pthread_cancelation_handler **___pthread_get_cleanup_stack (void) attri
#if IS_IN (libpthread)
hidden_proto (__pthread_key_create)
+hidden_proto (__pthread_getspecific)
+hidden_proto (__pthread_setspecific)
hidden_proto (_pthread_mutex_init)
#endif
diff --git a/sysdeps/i386/atomic-machine.h b/sysdeps/i386/atomic-machine.h
index 272da5dd8f..8e4169c05d 100644
--- a/sysdeps/i386/atomic-machine.h
+++ b/sysdeps/i386/atomic-machine.h
@@ -67,35 +67,26 @@ typedef uintmax_t uatomic_max_t;
#define __arch_c_compare_and_exchange_val_8_acq(mem, newval, oldval) \
({ __typeof (*mem) ret; \
- __asm __volatile ("cmpl $0, %%gs:%P5\n\t" \
- "je 0f\n\t" \
- "lock\n" \
- "0:\tcmpxchgb %b2, %1" \
+ __asm __volatile ("lock\n" \
+ "\tcmpxchgb %b2, %1" \
: "=a" (ret), "=m" (*mem) \
- : "q" (newval), "m" (*mem), "0" (oldval), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "q" (newval), "m" (*mem), "0" (oldval)); \
ret; })
#define __arch_c_compare_and_exchange_val_16_acq(mem, newval, oldval) \
({ __typeof (*mem) ret; \
- __asm __volatile ("cmpl $0, %%gs:%P5\n\t" \
- "je 0f\n\t" \
- "lock\n" \
- "0:\tcmpxchgw %w2, %1" \
+ __asm __volatile ("lock\n" \
+ "\tcmpxchgw %w2, %1" \
: "=a" (ret), "=m" (*mem) \
- : "r" (newval), "m" (*mem), "0" (oldval), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "r" (newval), "m" (*mem), "0" (oldval)); \
ret; })
#define __arch_c_compare_and_exchange_val_32_acq(mem, newval, oldval) \
({ __typeof (*mem) ret; \
- __asm __volatile ("cmpl $0, %%gs:%P5\n\t" \
- "je 0f\n\t" \
- "lock\n" \
- "0:\tcmpxchgl %2, %1" \
+ __asm __volatile ("lock\n" \
+ "\tcmpxchgl %2, %1" \
: "=a" (ret), "=m" (*mem) \
- : "r" (newval), "m" (*mem), "0" (oldval), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "r" (newval), "m" (*mem), "0" (oldval)); \
ret; })
/* XXX We do not really need 64-bit compare-and-exchange. At least
@@ -136,10 +127,8 @@ typedef uintmax_t uatomic_max_t;
# define __arch_c_compare_and_exchange_val_64_acq(mem, newval, oldval) \
({ __typeof (*mem) ret; \
__asm __volatile ("xchgl %2, %%ebx\n\t" \
- "cmpl $0, %%gs:%P7\n\t" \
- "je 0f\n\t" \
"lock\n" \
- "0:\tcmpxchg8b %1\n\t" \
+ "\tcmpxchg8b %1\n\t" \
"xchgl %2, %%ebx" \
: "=A" (ret), "=m" (*mem) \
: "DS" (((unsigned long long int) (newval)) \
@@ -147,8 +136,7 @@ typedef uintmax_t uatomic_max_t;
"c" (((unsigned long long int) (newval)) >> 32), \
"m" (*mem), "a" (((unsigned long long int) (oldval)) \
& 0xffffffff), \
- "d" (((unsigned long long int) (oldval)) >> 32), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ "d" (((unsigned long long int) (oldval)) >> 32)); \
ret; })
# else
# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
@@ -165,18 +153,15 @@ typedef uintmax_t uatomic_max_t;
# define __arch_c_compare_and_exchange_val_64_acq(mem, newval, oldval) \
({ __typeof (*mem) ret; \
- __asm __volatile ("cmpl $0, %%gs:%P7\n\t" \
- "je 0f\n\t" \
- "lock\n" \
- "0:\tcmpxchg8b %1" \
+ __asm __volatile ("lock\n" \
+ "\tcmpxchg8b %1" \
: "=A" (ret), "=m" (*mem) \
: "b" (((unsigned long long int) (newval)) \
& 0xffffffff), \
"c" (((unsigned long long int) (newval)) >> 32), \
"m" (*mem), "a" (((unsigned long long int) (oldval)) \
& 0xffffffff), \
- "d" (((unsigned long long int) (oldval)) >> 32), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ "d" (((unsigned long long int) (oldval)) >> 32)); \
ret; })
# endif
#endif
@@ -211,18 +196,15 @@ typedef uintmax_t uatomic_max_t;
if (sizeof (*mem) == 1) \
__asm __volatile (lock "xaddb %b0, %1" \
: "=q" (__result), "=m" (*mem) \
- : "0" (__addval), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "0" (__addval), "m" (*mem)); \
else if (sizeof (*mem) == 2) \
__asm __volatile (lock "xaddw %w0, %1" \
: "=r" (__result), "=m" (*mem) \
- : "0" (__addval), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "0" (__addval), "m" (*mem)); \
else if (sizeof (*mem) == 4) \
__asm __volatile (lock "xaddl %0, %1" \
: "=r" (__result), "=m" (*mem) \
- : "0" (__addval), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "0" (__addval), "m" (*mem)); \
else \
{ \
__typeof (mem) __memp = (mem); \
@@ -239,7 +221,7 @@ typedef uintmax_t uatomic_max_t;
__sync_fetch_and_add (mem, value)
#define __arch_exchange_and_add_cprefix \
- "cmpl $0, %%gs:%P4\n\tje 0f\n\tlock\n0:\t"
+ "lock\n\t"
#define catomic_exchange_and_add(mem, value) \
__arch_exchange_and_add_body (__arch_exchange_and_add_cprefix, __arch_c, \
@@ -255,18 +237,15 @@ typedef uintmax_t uatomic_max_t;
else if (sizeof (*mem) == 1) \
__asm __volatile (lock "addb %b1, %0" \
: "=m" (*mem) \
- : "iq" (value), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "iq" (value), "m" (*mem)); \
else if (sizeof (*mem) == 2) \
__asm __volatile (lock "addw %w1, %0" \
: "=m" (*mem) \
- : "ir" (value), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "ir" (value), "m" (*mem)); \
else if (sizeof (*mem) == 4) \
__asm __volatile (lock "addl %1, %0" \
: "=m" (*mem) \
- : "ir" (value), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "ir" (value), "m" (*mem)); \
else \
{ \
__typeof (value) __addval = (value); \
@@ -284,7 +263,7 @@ typedef uintmax_t uatomic_max_t;
__arch_add_body (LOCK_PREFIX, __arch, mem, value)
#define __arch_add_cprefix \
- "cmpl $0, %%gs:%P3\n\tje 0f\n\tlock\n0:\t"
+ "lock\n\t"
#define catomic_add(mem, value) \
__arch_add_body (__arch_add_cprefix, __arch_c, mem, value)
@@ -333,18 +312,15 @@ typedef uintmax_t uatomic_max_t;
if (sizeof (*mem) == 1) \
__asm __volatile (lock "incb %b0" \
: "=m" (*mem) \
- : "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "m" (*mem)); \
else if (sizeof (*mem) == 2) \
__asm __volatile (lock "incw %w0" \
: "=m" (*mem) \
- : "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "m" (*mem)); \
else if (sizeof (*mem) == 4) \
__asm __volatile (lock "incl %0" \
: "=m" (*mem) \
- : "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "m" (*mem)); \
else \
{ \
__typeof (mem) __memp = (mem); \
@@ -360,7 +336,7 @@ typedef uintmax_t uatomic_max_t;
#define atomic_increment(mem) __arch_increment_body (LOCK_PREFIX, __arch, mem)
#define __arch_increment_cprefix \
- "cmpl $0, %%gs:%P2\n\tje 0f\n\tlock\n0:\t"
+ "lock\n\t"
#define catomic_increment(mem) \
__arch_increment_body (__arch_increment_cprefix, __arch_c, mem)
@@ -390,18 +366,15 @@ typedef uintmax_t uatomic_max_t;
if (sizeof (*mem) == 1) \
__asm __volatile (lock "decb %b0" \
: "=m" (*mem) \
- : "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "m" (*mem)); \
else if (sizeof (*mem) == 2) \
__asm __volatile (lock "decw %w0" \
: "=m" (*mem) \
- : "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "m" (*mem)); \
else if (sizeof (*mem) == 4) \
__asm __volatile (lock "decl %0" \
: "=m" (*mem) \
- : "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "m" (*mem)); \
else \
{ \
__typeof (mem) __memp = (mem); \
@@ -417,7 +390,7 @@ typedef uintmax_t uatomic_max_t;
#define atomic_decrement(mem) __arch_decrement_body (LOCK_PREFIX, __arch, mem)
#define __arch_decrement_cprefix \
- "cmpl $0, %%gs:%P2\n\tje 0f\n\tlock\n0:\t"
+ "lock\n\t"
#define catomic_decrement(mem) \
__arch_decrement_body (__arch_decrement_cprefix, __arch_c, mem)
@@ -488,24 +461,21 @@ typedef uintmax_t uatomic_max_t;
if (sizeof (*mem) == 1) \
__asm __volatile (lock "andb %b1, %0" \
: "=m" (*mem) \
- : "iq" (mask), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "iq" (mask), "m" (*mem)); \
else if (sizeof (*mem) == 2) \
__asm __volatile (lock "andw %w1, %0" \
: "=m" (*mem) \
- : "ir" (mask), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "ir" (mask), "m" (*mem)); \
else if (sizeof (*mem) == 4) \
__asm __volatile (lock "andl %1, %0" \
: "=m" (*mem) \
- : "ir" (mask), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "ir" (mask), "m" (*mem)); \
else \
abort (); \
} while (0)
#define __arch_cprefix \
- "cmpl $0, %%gs:%P3\n\tje 0f\n\tlock\n0:\t"
+ "lock\n\t"
#define atomic_and(mem, mask) __arch_and_body (LOCK_PREFIX, mem, mask)
@@ -517,18 +487,15 @@ typedef uintmax_t uatomic_max_t;
if (sizeof (*mem) == 1) \
__asm __volatile (lock "orb %b1, %0" \
: "=m" (*mem) \
- : "iq" (mask), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "iq" (mask), "m" (*mem)); \
else if (sizeof (*mem) == 2) \
__asm __volatile (lock "orw %w1, %0" \
: "=m" (*mem) \
- : "ir" (mask), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "ir" (mask), "m" (*mem)); \
else if (sizeof (*mem) == 4) \
__asm __volatile (lock "orl %1, %0" \
: "=m" (*mem) \
- : "ir" (mask), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "ir" (mask), "m" (*mem)); \
else \
abort (); \
} while (0)
diff --git a/sysdeps/mach/Makefile b/sysdeps/mach/Makefile
index 475894b046..1d48168a04 100644
--- a/sysdeps/mach/Makefile
+++ b/sysdeps/mach/Makefile
@@ -35,7 +35,7 @@ endif
# because it's different in Darwin and the conditional crap is
# too much trouble. This should suffice for getting the mach/Makefile
# rules invoked when they need to be.
-mach-before-compile := $(mach-objpfx)mach-shortcuts.h \
+mach-before-compile := $(mach-objpfx)mach-shortcuts.h $(mach-objpfx)mach/mach_interface.h \
$(patsubst %,$(mach-objpfx)mach/mach_%.h,\
port host)
diff --git a/sysdeps/mach/hurd/Makefile b/sysdeps/mach/hurd/Makefile
index 3a853a6cd9..e15341ca8d 100644
--- a/sysdeps/mach/hurd/Makefile
+++ b/sysdeps/mach/hurd/Makefile
@@ -194,6 +194,10 @@ ifeq (hurd, $(subdir))
sysdep_routines += cthreads
endif
+ifeq (io, $(subdir))
+sysdep_routines += f_setlk
+endif
+
ifeq ($(subdir),sunrpc)
sysdep_headers += nfs/nfs.h
endif
diff --git a/sysdeps/mach/hurd/bind.c b/sysdeps/mach/hurd/bind.c
index fae826d534..c057500348 100644
--- a/sysdeps/mach/hurd/bind.c
+++ b/sysdeps/mach/hurd/bind.c
@@ -48,7 +48,7 @@ __bind (int fd, __CONST_SOCKADDR_ARG addrarg, socklen_t len)
return -1;
/* Create a new, unlinked node in the target directory. */
- err = __dir_mkfile (dir, O_CREAT, 0666 & ~_hurd_umask, &node);
+ err = __dir_mkfile (dir, O_CREAT, 0666, &node);
if (! err)
{
@@ -76,11 +76,16 @@ __bind (int fd, __CONST_SOCKADDR_ARG addrarg, socklen_t len)
err = EGRATUITOUS;
if (! err)
{
- /* Link the node, now a socket with proper mode, into the
- target directory. */
- err = __dir_link (dir, node, n, 1);
- if (err == EEXIST)
- err = EADDRINUSE;
+ /* Fix the access mode before showing the file. */
+ err = __file_chmod (node, 0666 & ~_hurd_umask);
+ if (! err)
+ {
+ /* Link the node, now a socket with proper mode, into the
+ target directory. */
+ err = __dir_link (dir, node, n, 1);
+ if (err == EEXIST)
+ err = EADDRINUSE;
+ }
if (err)
__mach_port_deallocate (__mach_task_self (), aport);
}
diff --git a/sysdeps/mach/hurd/bits/fcntl.h b/sysdeps/mach/hurd/bits/fcntl.h
index 2cfaa872a5..ef9b501167 100644
--- a/sysdeps/mach/hurd/bits/fcntl.h
+++ b/sysdeps/mach/hurd/bits/fcntl.h
@@ -163,9 +163,18 @@
# define F_GETOWN 5 /* Get owner (receiver of SIGIO). */
# define F_SETOWN 6 /* Set owner (receiver of SIGIO). */
#endif
-#define F_GETLK 7 /* Get record locking info. */
-#define F_SETLK 8 /* Set record locking info (non-blocking). */
-#define F_SETLKW 9 /* Set record locking info (blocking). */
+#ifdef __USE_FILE_OFFSET64
+# define F_GETLK F_GETLK64
+# define F_SETLK F_SETLK64
+# define F_SETLKW F_SETLKW64
+#else
+# define F_GETLK 7 /* Get record locking info. */
+# define F_SETLK 8 /* Set record locking info (non-blocking). */
+# define F_SETLKW 9 /* Set record locking info (blocking). */
+#endif
+#define F_GETLK64 10 /* Get record locking info. */
+#define F_SETLK64 11 /* Set record locking info (non-blocking). */
+#define F_SETLKW64 12 /* Set record locking info (blocking). */
#ifdef __USE_XOPEN2K8
# define F_DUPFD_CLOEXEC 1030 /* Duplicate, set FD_CLOEXEC on new one. */
diff --git a/sysdeps/mach/hurd/bits/sigaction.h b/sysdeps/mach/hurd/bits/sigaction.h
new file mode 100644
index 0000000000..444947c62b
--- /dev/null
+++ b/sysdeps/mach/hurd/bits/sigaction.h
@@ -0,0 +1,86 @@
+/* Copyright (C) 1991-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _BITS_SIGACTION_H
+#define _BITS_SIGACTION_H 1
+
+#ifndef _SIGNAL_H
+# error "Never include <bits/sigaction.h> directly; use <signal.h> instead."
+#endif
+
+/* These definitions match those used by the 4.4 BSD kernel.
+ If the operating system has a `sigaction' system call that correctly
+ implements the POSIX.1 behavior, there should be a system-dependent
+ version of this file that defines `struct sigaction' and the `SA_*'
+ constants appropriately. */
+
+/* Structure describing the action to be taken when a signal arrives. */
+struct sigaction
+ {
+ /* Signal handler. */
+#if defined __USE_POSIX199309 || defined __USE_XOPEN_EXTENDED
+ union
+ {
+ /* Used if SA_SIGINFO is not set. */
+ __sighandler_t sa_handler;
+ /* Used if SA_SIGINFO is set. */
+ void (*sa_sigaction) (int, siginfo_t *, void *);
+ }
+ __sigaction_handler;
+# define sa_handler __sigaction_handler.sa_handler
+# define sa_sigaction __sigaction_handler.sa_sigaction
+#else
+ __sighandler_t sa_handler;
+#endif
+
+ /* Additional set of signals to be blocked. */
+ __sigset_t sa_mask;
+
+ /* Special flags. */
+ int sa_flags;
+ };
+
+/* Bits in `sa_flags'. */
+#if defined __USE_XOPEN_EXTENDED || defined __USE_MISC
+# define SA_ONSTACK 0x0001 /* Take signal on signal stack. */
+#endif
+#if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8
+# define SA_RESTART 0x0002 /* Restart syscall on signal return. */
+# define SA_NODEFER 0x0010 /* Don't automatically block the signal when
+ its handler is being executed. */
+# define SA_RESETHAND 0x0004 /* Reset to SIG_DFL on entry to handler. */
+#endif
+#define SA_NOCLDSTOP 0x0008 /* Don't send SIGCHLD when children stop. */
+#define SA_SIGINFO 0x0040 /* Signal handler with SA_SIGINFO args */
+
+#ifdef __USE_MISC
+# define SA_INTERRUPT 0 /* Historical no-op ("not SA_RESTART"). */
+
+/* Some aliases for the SA_ constants. */
+# define SA_NOMASK SA_NODEFER
+# define SA_ONESHOT SA_RESETHAND
+# define SA_STACK SA_ONSTACK
+#endif
+
+
+/* Values for the HOW argument to `sigprocmask'. */
+#define SIG_BLOCK 1 /* Block signals. */
+#define SIG_UNBLOCK 2 /* Unblock signals. */
+#define SIG_SETMASK 3 /* Set the set of blocked signals. */
+
+#endif
diff --git a/sysdeps/mach/hurd/brk.c b/sysdeps/mach/hurd/brk.c
index f8272e5f22..bc95789fb1 100644
--- a/sysdeps/mach/hurd/brk.c
+++ b/sysdeps/mach/hurd/brk.c
@@ -143,8 +143,12 @@ init_brk (void)
/* If _hurd_brk is already set, don't change it. The assumption is that
it was set in a previous run before something like Emacs's unexec was
called and dumped all the data up to the break at that point. */
- if (_hurd_brk == 0)
+ if (_hurd_brk == 0) {
_hurd_brk = (vm_address_t) &_end;
+ if (_hurd_brk < 0x8000000)
+ /* XXX: PIE case, get out of library area */
+ _hurd_brk = 0x8000000;
+ }
pagend = round_page (_hurd_brk);
diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c
index b72913d3ba..d82f3609d3 100644
--- a/sysdeps/mach/hurd/dl-sysdep.c
+++ b/sysdeps/mach/hurd/dl-sysdep.c
@@ -92,12 +92,28 @@ static void fmh(void) {
max=a; break;}
fmha=a+=fmhs;}
if (err) assert(err==KERN_NO_SPACE);
- if (!fmha)fmhs=0;else{
- fmhs=max-fmha;
- err = __vm_map (__mach_task_self (),
- &fmha, fmhs, 0, 0, MACH_PORT_NULL, 0, 1,
- VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_COPY);
- assert_perror(err);}
+ if (!fmha)
+ fmhs=0;
+ else
+ while (1) {
+ fmhs=max-fmha;
+ if (fmhs == 0)
+ break;
+ err = __vm_map (__mach_task_self (),
+ &fmha, fmhs, 0, 0, MACH_PORT_NULL, 0, 1,
+ VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_COPY);
+ if (!err)
+ break;
+ if (err != KERN_INVALID_ADDRESS && err != KERN_NO_SPACE)
+ assert_perror(err);
+ vm_address_t new_max = (max - 1) & 0xf0000000U;
+ if (new_max >= max) {
+ fmhs = 0;
+ fmha = 0;
+ break;
+ }
+ max = new_max;
+ }
}
/* XXX loser kludge for vm_map kernel bug */
#endif
diff --git a/sysdeps/mach/hurd/f_setlk.c b/sysdeps/mach/hurd/f_setlk.c
new file mode 100644
index 0000000000..6e1b308756
--- /dev/null
+++ b/sysdeps/mach/hurd/f_setlk.c
@@ -0,0 +1,68 @@
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* XXX
+ We need new RPCs to support POSIX.1 fcntl file locking!!
+ For the time being we support the whole-file case only,
+ with all kinds of WRONG WRONG WRONG semantics,
+ by using flock. This is definitely the Wrong Thing,
+ but it might be better than nothing (?). */
+int
+__f_setlk (int fd, int type, int whence, __off64_t start, __off64_t len, int wait)
+{
+ int cmd = 0;
+
+ switch (type)
+ {
+ case F_RDLCK: cmd |= LOCK_SH | __LOCK_ATOMIC; break;
+ case F_WRLCK: cmd |= LOCK_EX | __LOCK_ATOMIC; break;
+ case F_UNLCK: cmd = LOCK_UN; break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (wait == 0)
+ cmd |= LOCK_NB;
+
+ switch (whence)
+ {
+ case SEEK_SET:
+ if (start == 0 && len == 0) /* Whole file request. */
+ break;
+ /* It seems to be common for applications to lock the first
+ byte of the file when they are really doing whole-file locking.
+ So, since it's so wrong already, might as well do that too. */
+ if (start == 0 && len == 1)
+ break;
+ /* FALLTHROUGH */
+ case SEEK_CUR:
+ case SEEK_END:
+ errno = ENOTSUP;
+ return -1;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ return __flock (fd, cmd);
+}
diff --git a/sysdeps/mach/hurd/faccessat.c b/sysdeps/mach/hurd/faccessat.c
index d9bceaada7..c81c310af0 100644
--- a/sysdeps/mach/hurd/faccessat.c
+++ b/sysdeps/mach/hurd/faccessat.c
@@ -170,6 +170,7 @@ __faccessat_common (int fd, const char *file, int type, int at_flags,
__mutex_unlock (&_hurd_id.lock);
HURD_CRITICAL_END;
+ /* FIXME: handle EINTR! */
if (rcrdir != MACH_PORT_NULL)
__mach_port_deallocate (__mach_task_self (), rcrdir);
diff --git a/sysdeps/mach/hurd/fcntl.c b/sysdeps/mach/hurd/fcntl.c
index 598317d811..4241f7b844 100644
--- a/sysdeps/mach/hurd/fcntl.c
+++ b/sysdeps/mach/hurd/fcntl.c
@@ -21,6 +21,7 @@
#include <hurd/fd.h>
#include <stdarg.h>
#include <sys/file.h> /* XXX for LOCK_* */
+#include "f_setlk.h"
/* Perform file control operations on FD. */
int
@@ -128,56 +129,48 @@ __libc_fcntl (int fd, int cmd, ...)
case F_SETLK:
case F_SETLKW:
{
- /* XXX
- We need new RPCs to support POSIX.1 fcntl file locking!!
- For the time being we support the whole-file case only,
- with all kinds of WRONG WRONG WRONG semantics,
- by using flock. This is definitely the Wrong Thing,
- but it might be better than nothing (?). */
struct flock *fl = va_arg (ap, struct flock *);
+ int wait = 0;
va_end (ap);
switch (cmd)
{
case F_GETLK:
errno = ENOSYS;
return -1;
+ case F_SETLKW:
+ wait = 1;
+ /* FALLTHROUGH */
case F_SETLK:
- cmd = LOCK_NB;
- break;
- default:
- cmd = 0;
- break;
- }
- switch (fl->l_type)
- {
- case F_RDLCK: cmd |= LOCK_SH; break;
- case F_WRLCK: cmd |= LOCK_EX; break;
- case F_UNLCK: cmd |= LOCK_UN; break;
+ return __f_setlk (fd, fl->l_type, fl->l_whence,
+ fl->l_start, fl->l_len, wait);
default:
errno = EINVAL;
return -1;
}
- switch (fl->l_whence)
+ }
+
+ case F_GETLK64:
+ case F_SETLK64:
+ case F_SETLKW64:
+ {
+ struct flock64 *fl = va_arg (ap, struct flock64 *);
+ int wait = 0;
+ va_end (ap);
+ switch (cmd)
{
- case SEEK_SET:
- if (fl->l_start == 0 && fl->l_len == 0) /* Whole file request. */
- break;
- /* It seems to be common for applications to lock the first
- byte of the file when they are really doing whole-file locking.
- So, since it's so wrong already, might as well do that too. */
- if (fl->l_start == 0 && fl->l_len == 1)
- break;
- /* FALLTHROUGH */
- case SEEK_CUR:
- case SEEK_END:
- errno = ENOTSUP;
+ case F_GETLK64:
+ errno = ENOSYS;
return -1;
+ case F_SETLKW64:
+ wait = 1;
+ /* FALLTHROUGH */
+ case F_SETLK64:
+ return __f_setlk (fd, fl->l_type, fl->l_whence,
+ fl->l_start, fl->l_len, wait);
default:
errno = EINVAL;
return -1;
}
-
- return __flock (fd, cmd);
}
case F_GETFL: /* Get per-open flags. */
diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c
index 2d1e64c8d1..f85fb56962 100644
--- a/sysdeps/mach/hurd/fork.c
+++ b/sysdeps/mach/hurd/fork.c
@@ -444,6 +444,7 @@ __fork (void)
(err = __mach_port_insert_right (newtask, ss->thread,
thread, MACH_MSG_TYPE_COPY_SEND)))
LOSE;
+ /* XXX consumed? (_hurd_sigthread is no more) */
if (thread_refs > 1 &&
(err = __mach_port_mod_refs (newtask, ss->thread,
MACH_PORT_RIGHT_SEND,
@@ -608,10 +609,6 @@ __fork (void)
for (i = 0; i < _hurd_nports; ++i)
__spin_unlock (&_hurd_ports[i].lock);
- /* We are one of the (exactly) two threads in this new task, we
- will take the task-global signals. */
- _hurd_sigthread = ss->thread;
-
/* Claim our sigstate structure and unchain the rest: the
threads existed in the parent task but don't exist in this
task (the child process). Delay freeing them until later
@@ -631,6 +628,25 @@ __fork (void)
ss->next = NULL;
_hurd_sigstates = ss;
__mutex_unlock (&_hurd_siglock);
+ /* Earlier on, the global sigstate may have been tainted and now needs to
+ be reinitialized. Nobody is interested in its present state anymore:
+ we're not, the signal thread will be restarted, and there are no other
+ threads.
+
+ We can't simply allocate a fresh global sigstate here, as
+ _hurd_thread_sigstate will call malloc and that will deadlock trying
+ to determine the current thread's sigstate. */
+#if 0
+ _hurd_thread_sigstate_init (_hurd_global_sigstate, MACH_PORT_NULL);
+#else
+ /* Only reinitialize the lock -- otherwise we might have to do additional
+ setup as done in hurdsig.c:_hurdsig_init. */
+ __spin_lock_init (&_hurd_global_sigstate->lock);
+#endif
+
+ /* We are one of the (exactly) two threads in this new task, we
+ will take the task-global signals. */
+ _hurd_sigstate_set_global_rcv (ss);
/* Fetch our new process IDs from the proc server. No need to
refetch our pgrp; it is always inherited from the parent (so
@@ -639,8 +655,13 @@ __fork (void)
err = __USEPORT (PROC, __proc_getpids (port, &_hurd_pid, &_hurd_ppid,
&_hurd_orphaned));
- /* Forking clears the trace flag. */
+ /* Forking clears the trace flag and pending masks. */
__sigemptyset (&_hurdsig_traced);
+ __sigemptyset (&_hurd_global_sigstate->pending);
+ __sigemptyset (&ss->pending);
+
+ /* Release malloc locks. */
+ _hurd_malloc_fork_child ();
/* Release malloc locks. */
_hurd_malloc_fork_child ();
@@ -692,6 +713,7 @@ __fork (void)
}
_hurd_critical_section_unlock (ss);
+ /* FIXME: handle EINTR */
if (!err)
{
diff --git a/sysdeps/mach/hurd/getcwd.c b/sysdeps/mach/hurd/getcwd.c
index c30b7c507b..34225a5d57 100644
--- a/sysdeps/mach/hurd/getcwd.c
+++ b/sysdeps/mach/hurd/getcwd.c
@@ -266,11 +266,6 @@ __hurd_canonicalize_directory_name_internal (file_t thisdir,
So the root is our current directory. */
*--file_namep = '/';
- if (thisid != rootid)
- /* We did not get to our root directory. The returned name should
- not begin with a slash. */
- ++file_namep;
-
memmove (file_name, file_namep, file_name + size - file_namep);
cleanup ();
return file_name;
@@ -309,13 +304,6 @@ __getcwd (char *buf, size_t size)
__USEPORT (CWDIR,
__hurd_canonicalize_directory_name_internal (port,
buf, size));
- if (cwd && cwd[0] != '/')
- {
- /* `cwd' is an unknown root directory. */
- if (buf == NULL)
- free (cwd);
- return __hurd_fail (EGRATUITOUS), NULL;
- }
return cwd;
}
weak_alias (__getcwd, getcwd)
diff --git a/sysdeps/mach/hurd/i386/bits/sigcontext.h b/sysdeps/mach/hurd/i386/bits/sigcontext.h
index f493bc9750..b6bf76a25e 100644
--- a/sysdeps/mach/hurd/i386/bits/sigcontext.h
+++ b/sysdeps/mach/hurd/i386/bits/sigcontext.h
@@ -97,6 +97,10 @@ struct sigcontext
#define sc_ps sc_efl
+/* The deprecated sigcode values below are passed as an extra, non-portable
+ argument to regular signal handlers. You should use SA_SIGINFO handlers
+ instead, which use the standard POSIX signal codes. */
+
/* Codes for SIGFPE. */
#define FPE_INTOVF_TRAP 0x1 /* integer overflow */
#define FPE_INTDIV_FAULT 0x2 /* integer divide by zero */
diff --git a/sysdeps/mach/hurd/i386/exc2signal.c b/sysdeps/mach/hurd/i386/exc2signal.c
index 57bc05df99..1b94e79e04 100644
--- a/sysdeps/mach/hurd/i386/exc2signal.c
+++ b/sysdeps/mach/hurd/i386/exc2signal.c
@@ -23,8 +23,8 @@
/* Translate the Mach exception codes, as received in an `exception_raise' RPC,
into a signal number and signal subcode. */
-void
-_hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
+static void
+exception2signal (struct hurd_signal_detail *detail, int *signo, int posix)
{
detail->error = 0;
@@ -36,44 +36,62 @@ _hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
break;
case EXC_BAD_ACCESS:
- if (detail->exc_code == KERN_INVALID_ADDRESS
- || detail->exc_code == KERN_PROTECTION_FAILURE
- || detail->exc_code == KERN_WRITE_PROTECTION_FAILURE)
- *signo = SIGSEGV;
- else
- *signo = SIGBUS;
- detail->code = detail->exc_subcode;
+ switch (detail->exc_code)
+ {
+ case KERN_INVALID_ADDRESS:
+ case KERN_MEMORY_FAILURE:
+ *signo = SIGSEGV;
+ detail->code = posix ? SEGV_MAPERR : detail->exc_subcode;
+ break;
+
+ case KERN_PROTECTION_FAILURE:
+ case KERN_WRITE_PROTECTION_FAILURE:
+ *signo = SIGSEGV;
+ detail->code = posix ? SEGV_ACCERR : detail->exc_subcode;
+ break;
+
+ default:
+ *signo = SIGBUS;
+ detail->code = posix ? BUS_ADRERR : detail->exc_subcode;
+ break;
+ }
detail->error = detail->exc_code;
break;
case EXC_BAD_INSTRUCTION:
*signo = SIGILL;
- if (detail->exc_code == EXC_I386_INVOP)
- detail->code = ILL_INVOPR_FAULT;
- else if (detail->exc_code == EXC_I386_STKFLT)
- detail->code = ILL_STACK_FAULT;
- else
- detail->code = 0;
+ switch (detail->exc_code)
+ {
+ case EXC_I386_INVOP:
+ detail->code = posix ? ILL_ILLOPC : ILL_INVOPR_FAULT;
+ break;
+
+ case EXC_I386_STKFLT:
+ detail->code = posix ? ILL_BADSTK : ILL_STACK_FAULT;
+ break;
+
+ default:
+ detail->code = 0;
+ break;
+ }
break;
case EXC_ARITHMETIC:
+ *signo = SIGFPE;
switch (detail->exc_code)
{
case EXC_I386_DIV: /* integer divide by zero */
- *signo = SIGFPE;
- detail->code = FPE_INTDIV_FAULT;
+ detail->code = posix ? FPE_INTDIV : FPE_INTDIV_FAULT;
break;
case EXC_I386_INTO: /* integer overflow */
- *signo = SIGFPE;
- detail->code = FPE_INTOVF_TRAP;
+ detail->code = posix ? FPE_INTOVF : FPE_INTOVF_TRAP;
break;
/* These aren't anywhere documented or used in Mach 3.0. */
case EXC_I386_NOEXT:
case EXC_I386_EXTOVR:
default:
- *signo = SIGFPE;
detail->code = 0;
break;
@@ -82,51 +100,43 @@ _hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
Give an error code corresponding to the first bit set. */
if (detail->exc_subcode & FPS_IE)
{
- *signo = SIGILL;
- detail->code = ILL_FPEOPR_FAULT;
+ /* NB: We used to send SIGILL here but we can't distinguish
+ POSIX vs. legacy with respect to what signal we send. */
+ detail->code = posix ? FPE_FLTINV : 0 /*ILL_FPEOPR_FAULT*/;
}
else if (detail->exc_subcode & FPS_DE)
{
- *signo = SIGFPE;
- detail->code = FPE_FLTDNR_FAULT;
+ detail->code = posix ? FPE_FLTUND : FPE_FLTDNR_FAULT;
}
else if (detail->exc_subcode & FPS_ZE)
{
- *signo = SIGFPE;
- detail->code = FPE_FLTDIV_FAULT;
+ detail->code = posix ? FPE_FLTDIV : FPE_FLTDIV_FAULT;
}
else if (detail->exc_subcode & FPS_OE)
{
- *signo = SIGFPE;
- detail->code = FPE_FLTOVF_FAULT;
+ detail->code = posix ? FPE_FLTOVF : FPE_FLTOVF_FAULT;
}
else if (detail->exc_subcode & FPS_UE)
{
- *signo = SIGFPE;
- detail->code = FPE_FLTUND_FAULT;
+ detail->code = posix ? FPE_FLTUND : FPE_FLTUND_FAULT;
}
else if (detail->exc_subcode & FPS_PE)
{
- *signo = SIGFPE;
- detail->code = FPE_FLTINX_FAULT;
+ detail->code = posix ? FPE_FLTRES : FPE_FLTINX_FAULT;
}
else
{
- *signo = SIGFPE;
detail->code = 0;
}
break;
/* These two can only be arithmetic exceptions if we
- are in V86 mode, which sounds like emulation to me.
- (See Mach 3.0 i386/trap.c.) */
+ are in V86 mode. (See Mach 3.0 i386/trap.c.) */
case EXC_I386_EMERR:
- *signo = SIGFPE;
- detail->code = FPE_EMERR_FAULT;
+ detail->code = posix ? 0 : FPE_EMERR_FAULT;
break;
case EXC_I386_BOUND:
- *signo = SIGFPE;
- detail->code = FPE_EMBND_FAULT;
+ detail->code = posix ? FPE_FLTSUB : FPE_EMBND_FAULT;
break;
}
break;
@@ -143,7 +153,7 @@ _hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
if (detail->exc_code == EXC_I386_BOUND)
{
*signo = SIGFPE;
- detail->code = FPE_SUBRNG_FAULT;
+ detail->code = posix ? FPE_FLTSUB : FPE_SUBRNG_FAULT;
}
else
{
@@ -154,13 +164,33 @@ _hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
case EXC_BREAKPOINT:
*signo = SIGTRAP;
- if (detail->exc_code == EXC_I386_SGL)
- detail->code = DBG_SINGLE_TRAP;
- else if (detail->exc_code == EXC_I386_BPT)
- detail->code = DBG_BRKPNT_FAULT;
- else
- detail->code = 0;
+ switch (detail->exc_code)
+ {
+ case EXC_I386_SGL:
+ detail->code = posix ? TRAP_BRKPT : DBG_SINGLE_TRAP;
+ break;
+
+ case EXC_I386_BPT:
+ detail->code = posix ? TRAP_BRKPT : DBG_BRKPNT_FAULT;
+ break;
+
+ default:
+ detail->code = 0;
+ break;
+ }
break;
}
}
+
+void
+_hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
+{
+ exception2signal (detail, signo, 1);
+}
libc_hidden_def (_hurd_exception2signal)
+
+void
+_hurd_exception2signal_legacy (struct hurd_signal_detail *detail, int *signo)
+{
+ exception2signal (detail, signo, 0);
+}
diff --git a/sysdeps/mach/hurd/i386/getcontext.S b/sysdeps/mach/hurd/i386/getcontext.S
index b456158f21..8157ea420a 100644
--- a/sysdeps/mach/hurd/i386/getcontext.S
+++ b/sysdeps/mach/hurd/i386/getcontext.S
@@ -1,5 +1,5 @@
/* Save current context.
- Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
@@ -63,7 +63,7 @@ ENTRY(__getcontext)
movl %eax, 8(%esp)
movl $0, 4(%esp)
movl $SIG_BLOCK, (%esp)
- call HIDDEN_JUMPTARGET (__sigprocmask)
+ call JUMPTARGET (__sigprocmask)
addl $12, %esp
cfi_adjust_cfa_offset (-12)
/* Propagate %eax (and errno, in case). */
diff --git a/sysdeps/mach/hurd/i386/makecontext.S b/sysdeps/mach/hurd/i386/makecontext.S
index 7f3f6b0b90..072741a007 100644
--- a/sysdeps/mach/hurd/i386/makecontext.S
+++ b/sysdeps/mach/hurd/i386/makecontext.S
@@ -1,5 +1,5 @@
/* Create new context.
- Copyright (C) 2001,2002,2005,2007,2008,2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
diff --git a/sysdeps/mach/hurd/i386/setcontext.S b/sysdeps/mach/hurd/i386/setcontext.S
index 2294eb623a..8c09915dd3 100644
--- a/sysdeps/mach/hurd/i386/setcontext.S
+++ b/sysdeps/mach/hurd/i386/setcontext.S
@@ -1,5 +1,5 @@
/* Install given context.
- Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
@@ -33,7 +33,7 @@ ENTRY(__setcontext)
leal oSIGMASK(%eax), %eax
movl %eax, 4(%esp)
movl $SIG_SETMASK, (%esp)
- call HIDDEN_JUMPTARGET (__sigprocmask)
+ call JUMPTARGET (__sigprocmask)
addl $12, %esp
cfi_adjust_cfa_offset (-12)
testl %eax, %eax
diff --git a/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c
index 07633e17c8..126d2f9fc4 100644
--- a/sysdeps/mach/hurd/i386/sigreturn.c
+++ b/sysdeps/mach/hurd/i386/sigreturn.c
@@ -24,6 +24,36 @@ register int *sp asm ("%esp");
#include <stdlib.h>
#include <string.h>
+/* This is run on the thread stack after restoring it, to be able to
+ unlock SS off sigstack. */
+static void
+__sigreturn2 (int *usp)
+{
+ struct hurd_sigstate *ss = _hurd_self_sigstate ();
+ _hurd_sigstate_unlock (ss);
+
+ sp = usp;
+#define A(line) asm volatile (#line)
+ /* The members in the sigcontext are arranged in this order
+ so we can pop them easily. */
+
+ /* Pop the segment registers (except %cs and %ss, done last). */
+ A (popl %gs);
+ A (popl %fs);
+ A (popl %es);
+ A (popl %ds);
+ /* Pop the general registers. */
+ A (popa);
+ /* Pop the processor flags. */
+ A (popf);
+ /* Return to the saved PC. */
+ A (ret);
+
+ /* Firewall. */
+ A (hlt);
+#undef A
+}
+
int
__sigreturn (struct sigcontext *scp)
{
@@ -38,7 +68,7 @@ __sigreturn (struct sigcontext *scp)
}
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
/* Remove the link on the `active resources' chain added by
_hurd_setup_sighandler. Its purpose was to make sure
@@ -50,19 +80,19 @@ __sigreturn (struct sigcontext *scp)
ss->intr_port = scp->sc_intr_port;
/* Check for pending signals that were blocked by the old set. */
- if (ss->pending & ~ss->blocked)
+ if (_hurd_sigstate_pending (ss) & ~ss->blocked)
{
/* There are pending signals that just became unblocked. Wake up the
signal thread to deliver them. But first, squirrel away SCP where
the signal thread will notice it if it runs another handler, and
arrange to have us called over again in the new reality. */
ss->context = scp;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
__msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
/* If a pending signal was handled, sig_post never returned.
If it did return, the pending signal didn't run a handler;
proceed as usual. */
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
ss->context = NULL;
}
@@ -108,27 +138,19 @@ __sigreturn (struct sigcontext *scp)
*--usp = scp->sc_efl;
memcpy (usp -= 12, &scp->sc_i386_thread_state, 12 * sizeof (int));
- sp = usp;
-
-#define A(line) asm volatile (#line)
- /* The members in the sigcontext are arranged in this order
- so we can pop them easily. */
-
- /* Pop the segment registers (except %cs and %ss, done last). */
- A (popl %gs);
- A (popl %fs);
- A (popl %es);
- A (popl %ds);
- /* Pop the general registers. */
- A (popa);
- /* Pop the processor flags. */
- A (popf);
- /* Return to the saved PC. */
- A (ret);
+ /* Pass usp to __sigreturn2 so it can unwind itself easily. */
+ *(usp-1) = (int) usp;
+ --usp;
+ /* Bogus return address for __sigreturn2 */
+ *--usp = 0;
+ *--usp = (int) __sigreturn2;
+ /* Restore thread stack */
+ sp = usp;
+ /* Return into __sigreturn2. */
+ asm volatile ("ret");
/* Firewall. */
- A (hlt);
-#undef A
+ asm volatile ("hlt");
}
/* NOTREACHED */
diff --git a/sysdeps/mach/hurd/i386/swapcontext.S b/sysdeps/mach/hurd/i386/swapcontext.S
index fb45b70849..8780572afe 100644
--- a/sysdeps/mach/hurd/i386/swapcontext.S
+++ b/sysdeps/mach/hurd/i386/swapcontext.S
@@ -1,5 +1,5 @@
/* Save current context and install the given one.
- Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
@@ -62,7 +62,7 @@ ENTRY(__swapcontext)
leal oSIGMASK(%ecx), %eax
movl %eax, 4(%esp)
movl $SIG_SETMASK, (%esp)
- call HIDDEN_JUMPTARGET (__sigprocmask)
+ call JUMPTARGET (__sigprocmask)
addl $12, %esp
cfi_adjust_cfa_offset (-12)
testl %eax, %eax
diff --git a/sysdeps/mach/hurd/i386/trampoline.c b/sysdeps/mach/hurd/i386/trampoline.c
index 0e795f9389..7eca1db020 100644
--- a/sysdeps/mach/hurd/i386/trampoline.c
+++ b/sysdeps/mach/hurd/i386/trampoline.c
@@ -19,13 +19,66 @@
#include <hurd/signal.h>
#include <hurd/userlink.h>
#include <thread_state.h>
+#include <mach/exception.h>
#include <mach/machine/eflags.h>
#include <assert.h>
#include <errno.h>
#include "hurdfault.h"
#include <intr-msg.h>
+#include <sys/ucontext.h>
+/* Fill in a siginfo_t structure for SA_SIGINFO-enabled handlers. */
+static void fill_siginfo (siginfo_t *si, int signo,
+ const struct hurd_signal_detail *detail,
+ const struct machine_thread_all_state *state)
+{
+ si->si_signo = signo;
+ si->si_errno = detail->error;
+ si->si_code = detail->code;
+
+ /* XXX We would need a protocol change for sig_post to include
+ * this information. */
+ si->si_pid = -1;
+ si->si_uid = -1;
+
+ /* Address of the faulting instruction or memory access. */
+ if (detail->exc == EXC_BAD_ACCESS)
+ si->si_addr = (void *) detail->exc_subcode;
+ else
+ si->si_addr = (void *) state->basic.eip;
+
+ /* XXX On SIGCHLD, this should be the exit status of the child
+ * process. We would need a protocol change for the proc server
+ * to send this information along with the signal. */
+ si->si_status = 0;
+
+ si->si_band = 0; /* SIGPOLL is not supported yet. */
+ si->si_value.sival_int = 0; /* sigqueue() is not supported yet. */
+}
+
+/* Fill in a ucontext_t structure SA_SIGINFO-enabled handlers. */
+static void fill_ucontext (ucontext_t *uc, const struct sigcontext *sc)
+{
+ uc->uc_flags = 0;
+ uc->uc_link = NULL;
+ uc->uc_sigmask = sc->sc_mask;
+ uc->uc_stack.ss_sp = (__ptr_t) sc->sc_esp;
+ uc->uc_stack.ss_size = 0;
+ uc->uc_stack.ss_flags = 0;
+
+ /* Registers. */
+ memcpy (&uc->uc_mcontext.gregs[REG_GS], &sc->sc_gs,
+ (REG_TRAPNO - REG_GS) * sizeof (int));
+ uc->uc_mcontext.gregs[REG_TRAPNO] = 0;
+ uc->uc_mcontext.gregs[REG_ERR] = 0;
+ memcpy (&uc->uc_mcontext.gregs[REG_EIP], &sc->sc_eip,
+ (NGREG - REG_EIP) * sizeof (int));
+
+ /* XXX FPU state. */
+ memset (&uc->uc_mcontext.fpregs, 0, sizeof (fpregset_t));
+}
+
struct sigcontext *
_hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
int signo, struct hurd_signal_detail *detail,
@@ -37,20 +90,44 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
void firewall (void);
extern const void _hurd_intr_rpc_msg_cx_sp;
extern const void _hurd_intr_rpc_msg_sp_restored;
+ const struct sigaction *action;
void *volatile sigsp;
struct sigcontext *scp;
struct
{
int signo;
- long int sigcode;
- struct sigcontext *scp; /* Points to ctx, below. */
+ union
+ {
+ /* Extra arguments for traditional signal handlers */
+ struct
+ {
+ long int sigcode;
+ struct sigcontext *scp; /* Points to ctx, below. */
+ } legacy;
+
+ /* Extra arguments for SA_SIGINFO handlers */
+ struct
+ {
+ siginfo_t *siginfop; /* Points to siginfo, below. */
+ ucontext_t *uctxp; /* Points to uctx, below. */
+ } posix;
+ };
void *sigreturn_addr;
void *sigreturn_returns_here;
struct sigcontext *return_scp; /* Same; arg to sigreturn. */
+
+ /* NB: sigreturn assumes link is next to ctx. */
struct sigcontext ctx;
struct hurd_userlink link;
+ ucontext_t ucontext;
+ siginfo_t siginfo;
} *stackframe;
+ /* sigaction for preemptors */
+ static const struct sigaction legacy_sigaction = {
+ .sa_flags = SA_RESTART
+ };
+
if (ss->context)
{
/* We have a previous sigcontext that sigreturn was about
@@ -74,7 +151,15 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
interrupted RPC frame. */
state->basic.esp = state->basic.uesp;
- if ((ss->actions[signo].sa_flags & SA_ONSTACK) &&
+ action = & _hurd_sigstate_actions (ss) [signo];
+ if ( (action->sa_flags & SA_SIGINFO)
+ && handler != (__sighandler_t) action->sa_sigaction
+ || !(action->sa_flags & SA_SIGINFO)
+ && handler != action->sa_handler)
+ /* A signal preemptor took over, use legacy semantic. */
+ action = &legacy_sigaction;
+
+ if ((action->sa_flags & SA_ONSTACK) &&
!(ss->sigaltstack.ss_flags & (SS_DISABLE|SS_ONSTACK)))
{
sigsp = ss->sigaltstack.ss_sp + ss->sigaltstack.ss_size;
@@ -134,15 +219,9 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
= &stackframe->link.thread.next;
ss->active_resources = &stackframe->link;
- /* Set up the arguments for the signal handler. */
- stackframe->signo = signo;
- stackframe->sigcode = detail->code;
- stackframe->scp = stackframe->return_scp = scp = &stackframe->ctx;
- stackframe->sigreturn_addr = &__sigreturn;
- stackframe->sigreturn_returns_here = firewall; /* Crash on return. */
-
/* Set up the sigcontext from the current state of the thread. */
+ scp = &stackframe->ctx;
scp->sc_onstack = ss->sigaltstack.ss_flags & SS_ONSTACK ? 1 : 0;
/* struct sigcontext is laid out so that starting at sc_gs mimics a
@@ -156,6 +235,35 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
&state->fpu, &scp->sc_i386_float_state,
sizeof (state->fpu));
+ /* Set up the arguments for the signal handler. */
+ stackframe->signo = signo;
+ if (action->sa_flags & SA_SIGINFO)
+ {
+ stackframe->posix.siginfop = &stackframe->siginfo;
+ stackframe->posix.uctxp = &stackframe->ucontext;
+ fill_siginfo (&stackframe->siginfo, signo, detail, state);
+ fill_ucontext (&stackframe->ucontext, scp);
+ }
+ else
+ {
+ if (detail->exc)
+ {
+ int nsigno;
+ _hurd_exception2signal_legacy (detail, &nsigno);
+ assert (nsigno == signo);
+ }
+ else
+ detail->code = 0;
+
+ stackframe->legacy.sigcode = detail->code;
+ stackframe->legacy.scp = &stackframe->ctx;
+ }
+
+ /* Set up the bottom of the stack. */
+ stackframe->sigreturn_addr = &__sigreturn;
+ stackframe->sigreturn_returns_here = firewall; /* Crash on return. */
+ stackframe->return_scp = &stackframe->ctx;
+
_hurdsig_end_catch_fault ();
if (! ok)
diff --git a/sysdeps/mach/hurd/ifaddrs.c b/sysdeps/mach/hurd/ifaddrs.c
new file mode 100644
index 0000000000..02e47e04a4
--- /dev/null
+++ b/sysdeps/mach/hurd/ifaddrs.c
@@ -0,0 +1,310 @@
+/* getifaddrs -- get names and addresses of all network interfaces
+ Copyright (C) 2013-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <hurd.h>
+#include <hurd/paths.h>
+#include <hurd/lookup.h>
+#include <hurd/fs.h>
+
+/* Create a linked list of `struct ifaddrs' structures, one for each
+ network interface on the host machine. If successful, store the
+ list in *IFAP and return 0. On errors, return -1 and set `errno'. */
+int
+__getifaddrs (struct ifaddrs **ifap)
+{
+ /* XXX: Hackish. This assumes pfinet parameter style, and that the same
+ pfinet is on /servers/socket/2 and /servers/socket/26.
+
+ To be replaced by something like a netlink protocol, or fix ifreq into
+ using sockaddr_storage (but break existing compiled programs using it). */
+
+ file_t node;
+ char *argz = 0, *cur;
+ size_t argz_len = 0;
+ unsigned naddrs;
+ const char *ifa_name = NULL;
+ char *addr, *cidr_a;
+ int cidr;
+
+ node = __file_name_lookup (_SERVERS_SOCKET "/2", 0, 0666);
+
+ if (node == MACH_PORT_NULL)
+ return -1;
+
+ __file_get_fs_options (node, &argz, &argz_len);
+
+ __mach_port_deallocate (__mach_task_self (), node);
+
+ /* XXX: Two hardcoded for lo */
+ naddrs = 2;
+
+ for (cur = argz; cur < argz + argz_len; cur = cur + strlen (cur) + 1)
+ {
+ if (!strncmp (cur, "--address=", 10))
+ naddrs++;
+ else if (!strncmp (cur, "--address6=", 11))
+ naddrs++;
+ }
+
+ {
+ struct
+ {
+ struct ifaddrs ia;
+ struct sockaddr_storage addr, netmask, broadaddr;
+ char name[IF_NAMESIZE];
+ } *storage;
+ int i;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+
+ storage = malloc (naddrs * sizeof storage[0]);
+ if (storage == NULL)
+ {
+ __munmap (argz, argz_len);
+ return -1;
+ }
+
+ i = 0;
+
+ /* XXX: Hardcoded lo interface */
+ ifa_name = "lo";
+
+ /* 127.0.0.1/8 */
+ storage[i].ia.ifa_next = &storage[i + 1].ia;
+ storage[i].ia.ifa_name = strncpy (storage[i].name, ifa_name, sizeof (storage[i].name));
+
+ storage[i].ia.ifa_addr = (struct sockaddr *) &storage[i].addr;
+ sin = ((struct sockaddr_in *) &storage[i].addr);
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_port = 0;
+ sin->sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+ storage[i].ia.ifa_netmask = (struct sockaddr *) &storage[i].netmask;
+ sin = ((struct sockaddr_in *) &storage[i].netmask);
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_port = 0;
+ sin->sin_addr.s_addr = htonl (IN_CLASSA_NET);
+
+ storage[i].ia.ifa_broadaddr = (struct sockaddr *) &storage[i].addr;
+
+ storage[i].ia.ifa_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING;
+
+ storage[i].ia.ifa_data = NULL; /* Nothing here for now. */
+
+ i++;
+
+ /* ::1/128 */
+ storage[i].ia.ifa_next = &storage[i + 1].ia;
+ storage[i].ia.ifa_name = strncpy (storage[i].name, ifa_name, sizeof (storage[i].name));
+
+ storage[i].ia.ifa_addr = (struct sockaddr *) &storage[i].addr;
+ sin6 = ((struct sockaddr_in6 *) &storage[i].addr);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_port = 0;
+ sin6->sin6_flowinfo = 0;
+ inet_pton (AF_INET6, "::1", &sin6->sin6_addr);
+ sin6->sin6_scope_id = 0;
+
+ storage[i].ia.ifa_netmask = (struct sockaddr *) &storage[i].netmask;
+ sin6 = ((struct sockaddr_in6 *) &storage[i].netmask);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_port = 0;
+ sin6->sin6_flowinfo = 0;
+ inet_pton (AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", &sin6->sin6_addr);
+ sin6->sin6_scope_id = 0;
+
+ storage[i].ia.ifa_broadaddr = NULL;
+
+ storage[i].ia.ifa_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING;
+
+ storage[i].ia.ifa_data = NULL; /* Nothing here for now. */
+
+ for (cur = argz; cur < argz + argz_len; cur = cur + strlen (cur) + 1)
+ {
+ if (!strncmp (cur, "--interface=", 12))
+ {
+ ifa_name = cur + 12;
+ continue;
+ }
+
+ else if (!strncmp (cur, "--address=", 10))
+ {
+ i++;
+ /* IPv4 address */
+ addr = cur + 10;
+
+ storage[i].ia.ifa_next = &storage[i + 1].ia;
+ storage[i].ia.ifa_name = strncpy (storage[i].name, ifa_name, sizeof (storage[i].name));
+
+ storage[i].ia.ifa_addr = (struct sockaddr *) &storage[i].addr;
+ sin = ((struct sockaddr_in *) &storage[i].addr);
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_port = 0;
+ inet_pton (AF_INET, addr, &sin->sin_addr);
+
+ storage[i].ia.ifa_netmask = NULL;
+ storage[i].ia.ifa_broadaddr = NULL;
+
+ storage[i].ia.ifa_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_MULTICAST;
+ storage[i].ia.ifa_data = NULL; /* Nothing here for now. */
+ }
+
+ else if (!strncmp (cur, "--netmask=", 10))
+ {
+ /* IPv4 netmask */
+ addr = cur + 10;
+
+ storage[i].ia.ifa_netmask = (struct sockaddr *) &storage[i].netmask;
+ sin = ((struct sockaddr_in *) &storage[i].netmask);
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_port = 0;
+ inet_pton (AF_INET, addr, &sin->sin_addr);
+
+ storage[i].ia.ifa_broadaddr = (struct sockaddr *) &storage[i].broadaddr;
+ sin = ((struct sockaddr_in *) &storage[i].broadaddr);
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_port = 0;
+ sin->sin_addr.s_addr =
+ ((struct sockaddr_in *) &storage[i].addr)->sin_addr.s_addr
+ | ~(((struct sockaddr_in *) &storage[i].netmask)->sin_addr.s_addr);
+ }
+
+ else if (!strncmp (cur, "--peer=", 7))
+ {
+ /* IPv4 peer */
+ addr = cur + 7;
+
+ storage[i].ia.ifa_dstaddr = (struct sockaddr *) &storage[i].broadaddr;
+ sin = ((struct sockaddr_in *) &storage[i].broadaddr);
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_port = 0;
+ inet_pton (AF_INET, addr, &sin->sin_addr);
+
+ storage[i].ia.ifa_flags &= ~IFF_BROADCAST;
+ storage[i].ia.ifa_flags |= IFF_POINTOPOINT;
+ }
+
+ else if (!strncmp (cur, "--address6=", 11))
+ {
+ i++;
+ /* IPv6 address */
+ addr = cur + 11;
+ cidr_a = strchr (addr, '/');
+ if (!cidr_a)
+ {
+ /* No CIDR length?! Assume 64. */
+ addr = __strdup (addr);
+ cidr = 64;
+ }
+ else
+ {
+ addr = __strndup (addr, cidr_a - addr);
+ cidr = atoi (cidr_a + 1);
+ }
+
+ storage[i].ia.ifa_next = &storage[i + 1].ia;
+ storage[i].ia.ifa_name = strncpy (storage[i].name, ifa_name, sizeof (storage[i].name));
+
+ storage[i].ia.ifa_addr = (struct sockaddr *) &storage[i].addr;
+ sin6 = ((struct sockaddr_in6 *) &storage[i].addr);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_port = 0;
+ sin6->sin6_flowinfo = 0;
+ inet_pton (AF_INET6, addr, &sin6->sin6_addr);
+ sin6->sin6_scope_id = 0;
+
+ storage[i].ia.ifa_netmask = (struct sockaddr *) &storage[i].netmask;
+ sin6 = ((struct sockaddr_in6 *) &storage[i].netmask);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_port = 0;
+ sin6->sin6_flowinfo = 0;
+ sin6->sin6_addr.s6_addr32[0] = htonl (cidr >= 32 ? 0xffffffffUL : cidr <= 0 ? 0 : ~((1UL << ( 32 - cidr)) - 1));
+ sin6->sin6_addr.s6_addr32[1] = htonl (cidr >= 64 ? 0xffffffffUL : cidr <= 32 ? 0 : ~((1UL << ( 64 - cidr)) - 1));
+ sin6->sin6_addr.s6_addr32[2] = htonl (cidr >= 96 ? 0xffffffffUL : cidr <= 64 ? 0 : ~((1UL << ( 96 - cidr)) - 1));
+ sin6->sin6_addr.s6_addr32[3] = htonl (cidr >= 128 ? 0xffffffffUL : cidr <= 96 ? 0 : ~((1UL << (128 - cidr)) - 1));
+ sin6->sin6_scope_id = 0;
+
+ storage[i].ia.ifa_broadaddr = NULL;
+ storage[i].ia.ifa_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_MULTICAST;
+ storage[i].ia.ifa_data = NULL; /* Nothing here for now. */
+ free (addr);
+ }
+
+ else if (!strncmp (cur, "--peer6=", 8))
+ {
+ /* IPv6 peer */
+ addr = cur + 8;
+
+ storage[i].ia.ifa_dstaddr = (struct sockaddr *) &storage[i].broadaddr;
+ sin6 = ((struct sockaddr_in6 *) &storage[i].broadaddr);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_port = 0;
+ sin6->sin6_flowinfo = 0;
+ inet_pton (AF_INET6, addr, &sin6->sin6_addr);
+ sin6->sin6_scope_id = 0;
+
+ storage[i].ia.ifa_flags &= ~IFF_BROADCAST;
+ storage[i].ia.ifa_flags |= IFF_POINTOPOINT;
+ }
+ }
+
+ storage[i].ia.ifa_next = NULL;
+
+ *ifap = &storage[0].ia;
+ }
+
+ __munmap (argz, argz_len);
+
+ return 0;
+}
+weak_alias (__getifaddrs, getifaddrs)
+libc_hidden_def (__getifaddrs)
+#ifndef getifaddrs
+libc_hidden_weak (getifaddrs)
+#endif
+
+void
+__freeifaddrs (struct ifaddrs *ifa)
+{
+ free (ifa);
+}
+weak_alias (__freeifaddrs, freeifaddrs)
+libc_hidden_def (__freeifaddrs)
+libc_hidden_weak (freeifaddrs)
diff --git a/sysdeps/mach/hurd/jmp-unwind.c b/sysdeps/mach/hurd/jmp-unwind.c
index d269f9f61b..34fc7fe3f8 100644
--- a/sysdeps/mach/hurd/jmp-unwind.c
+++ b/sysdeps/mach/hurd/jmp-unwind.c
@@ -49,9 +49,8 @@ _longjmp_unwind (jmp_buf env, int val)
/* All access to SS->active_resources must take place inside a critical
section where signal handlers cannot run. */
- __spin_lock (&ss->lock);
- assert (! __spin_lock_locked (&ss->critical_section_lock));
__spin_lock (&ss->critical_section_lock);
+ __spin_lock (&ss->lock);
/* Remove local signal preemptors being unwound past. */
while (ss->preemptors &&
diff --git a/sysdeps/mach/hurd/kill.c b/sysdeps/mach/hurd/kill.c
index 7e64e7c9d7..f9c9a57030 100644
--- a/sysdeps/mach/hurd/kill.c
+++ b/sysdeps/mach/hurd/kill.c
@@ -64,7 +64,7 @@ __kill (pid_t pid, int sig)
{
if (msgport != MACH_PORT_NULL)
/* Send a signal message to his message port. */
- return __msg_sig_post (msgport, sig, 0, refport);
+ return __msg_sig_post (msgport, sig, SI_USER, refport);
/* The process has no message port. Perhaps try direct
frobnication of the task. */
diff --git a/sysdeps/mach/hurd/msync.c b/sysdeps/mach/hurd/msync.c
new file mode 100644
index 0000000000..a4b30f7b5b
--- /dev/null
+++ b/sysdeps/mach/hurd/msync.c
@@ -0,0 +1,93 @@
+/* msync -- Synchronize mapped memory to external storage. Mach version.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+#include <hurd/hurd.h>
+
+/* Synchronize the region starting at ADDR and extending LEN bytes with the
+ file it maps. Filesystem operations on a file being mapped are
+ unpredictable before this is done. */
+
+int
+msync (void *addr, size_t length, int flags)
+{
+ boolean_t should_flush = flags & MS_INVALIDATE ? 1 : 0;
+ boolean_t should_iosync = flags & MS_ASYNC ? 0 : 1;
+
+ vm_address_t cur = (vm_address_t) addr;
+ vm_address_t target = cur + length;
+
+ vm_size_t len;
+ vm_prot_t prot;
+ vm_prot_t max_prot;
+ vm_inherit_t inherit;
+ boolean_t shared;
+ memory_object_name_t obj;
+ vm_offset_t offset;
+
+ kern_return_t err;
+
+ if (flags & (MS_SYNC | MS_ASYNC) == (MS_SYNC | MS_ASYNC))
+ return __hurd_fail (EINVAL);
+
+ while (cur < target)
+ {
+ vm_address_t begin = cur;
+
+ err = __vm_region (__mach_task_self (),
+ &begin, &len, &prot, &max_prot, &inherit,
+ &shared, &obj, &offset);
+
+ if (err != KERN_SUCCESS)
+ return __hurd_fail (err);
+
+ if (begin > cur)
+ /* We were given an address before the first region,
+ or we found a hole. */
+ cur = begin;
+
+ if (cur >= target)
+ /* We were given an ending address within a hole. */
+ break;
+
+ if (MACH_PORT_VALID (obj))
+ {
+ vm_size_t sync_len;
+
+ if (begin + len > target)
+ sync_len = target - begin;
+ else
+ sync_len = len;
+
+ err = __vm_object_sync (obj, cur - begin + offset, sync_len,
+ should_flush, 1, should_iosync);
+ __mach_port_deallocate (__mach_task_self (), obj);
+
+ if (err)
+ return __hurd_fail (err);
+
+ }
+
+ cur = begin + len;
+ }
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/recvmsg.c b/sysdeps/mach/hurd/recvmsg.c
index 770ca7187b..220e6f70e9 100644
--- a/sysdeps/mach/hurd/recvmsg.c
+++ b/sysdeps/mach/hurd/recvmsg.c
@@ -23,6 +23,123 @@
#include <hurd/fd.h>
#include <hurd/socket.h>
+static unsigned
+contains_uid (unsigned int n, __uid_t uids[n], __uid_t uid)
+{
+ unsigned i;
+
+ for (i = 0; i < n; i++)
+ if (uids[i] == uid)
+ return 1;
+ return 0;
+}
+
+static unsigned
+contains_gid (unsigned int n, __gid_t gids[n], __gid_t gid)
+{
+ unsigned i;
+
+ for (i = 0; i < n; i++)
+ if (gids[i] == gid)
+ return 1;
+ return 0;
+}
+
+/* Check the passed credentials. */
+static error_t
+check_auth (mach_port_t rendezvous,
+ __pid_t pid,
+ __uid_t uid, __uid_t euid,
+ __gid_t gid,
+ int ngroups, __gid_t groups[ngroups])
+{
+ error_t err;
+ size_t neuids = CMGROUP_MAX, nauids = CMGROUP_MAX;
+ size_t negids = CMGROUP_MAX, nagids = CMGROUP_MAX;
+ __uid_t euids_buf[neuids], auids_buf[nauids];
+ __gid_t egids_buf[negids], agids_buf[nagids];
+ __uid_t *euids = euids_buf, *auids = auids_buf;
+ __gid_t *egids = egids_buf, *agids = agids_buf;
+
+ struct procinfo *pi = NULL;
+ mach_msg_type_number_t pi_size = 0;
+ int flags = PI_FETCH_TASKINFO;
+ char *tw = NULL;
+ size_t tw_size = 0;
+ unsigned i;
+
+ err = __mach_port_mod_refs (mach_task_self (), rendezvous,
+ MACH_PORT_RIGHT_SEND, 1);
+ if (err)
+ goto out;
+
+ do
+ err = __USEPORT
+ (AUTH, __auth_server_authenticate (port,
+ rendezvous, MACH_MSG_TYPE_COPY_SEND,
+ MACH_PORT_NULL, 0,
+ &euids, &neuids, &auids, &nauids,
+ &egids, &negids, &agids, &nagids));
+ while (err == EINTR);
+ if (err)
+ goto out;
+
+ /* Check whether this process indeed has these IDs */
+ if ( !contains_uid (neuids, euids, uid)
+ && !contains_uid (nauids, auids, uid)
+ || !contains_uid (neuids, euids, euid)
+ && !contains_uid (nauids, auids, euid)
+ || !contains_gid (negids, egids, gid)
+ && !contains_gid (nagids, agids, gid)
+ )
+ {
+ err = EIO;
+ goto out;
+ }
+
+ /* Check groups */
+ for (i = 0; i < ngroups; i++)
+ if ( !contains_gid (negids, egids, groups[i])
+ && !contains_gid (nagids, agids, groups[i]))
+ {
+ err = EIO;
+ goto out;
+ }
+
+ /* Check PID */
+ /* XXX: Using proc_getprocinfo until
+ proc_user_authenticate proc_server_authenticate is implemented
+ */
+ /* Get procinfo to check the owner. Maybe he faked the pid, but at least we
+ check the owner. */
+ err = __USEPORT (PROC, __proc_getprocinfo (port, pid, &flags,
+ (procinfo_t *)&pi,
+ &pi_size, &tw, &tw_size));
+ if (err)
+ goto out;
+
+ if ( !contains_uid (neuids, euids, pi->owner)
+ && !contains_uid (nauids, auids, pi->owner))
+ err = EIO;
+
+out:
+ __mach_port_deallocate (__mach_task_self (), rendezvous);
+ if (euids != euids_buf)
+ __vm_deallocate (__mach_task_self(), (vm_address_t) euids, neuids * sizeof(uid_t));
+ if (auids != auids_buf)
+ __vm_deallocate (__mach_task_self(), (vm_address_t) auids, nauids * sizeof(uid_t));
+ if (egids != egids_buf)
+ __vm_deallocate (__mach_task_self(), (vm_address_t) egids, negids * sizeof(uid_t));
+ if (agids != agids_buf)
+ __vm_deallocate (__mach_task_self(), (vm_address_t) agids, nagids * sizeof(uid_t));
+ if (tw_size)
+ __vm_deallocate (__mach_task_self(), (vm_address_t) tw, tw_size);
+ if (pi_size)
+ __vm_deallocate (__mach_task_self(), (vm_address_t) pi, pi_size);
+
+ return err;
+}
+
/* Receive a message as described by MESSAGE from socket FD.
Returns the number of bytes read or -1 for errors. */
ssize_t
@@ -32,13 +149,34 @@ __libc_recvmsg (int fd, struct msghdr *message, int flags)
addr_port_t aport;
char *data = NULL;
mach_msg_type_number_t len = 0;
- mach_port_t *ports;
+ mach_port_t *ports, *newports = NULL;
mach_msg_type_number_t nports = 0;
+ struct cmsghdr *cmsg;
char *cdata = NULL;
mach_msg_type_number_t clen = 0;
size_t amount;
char *buf;
- int i;
+ int nfds, *opened_fds = NULL;
+ int i, ii, j;
+ int newfds;
+
+ error_t reauthenticate (mach_port_t port, mach_port_t *result)
+ {
+ error_t err;
+ mach_port_t ref;
+ ref = __mach_reply_port ();
+ do
+ err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND);
+ while (err == EINTR);
+ if (!err)
+ do
+ err = __USEPORT (AUTH, __auth_user_authenticate (port,
+ ref, MACH_MSG_TYPE_MAKE_SEND,
+ result));
+ while (err == EINTR);
+ __mach_port_destroy (__mach_task_self (), ref);
+ return err;
+ }
/* Find the total number of bytes to be read. */
amount = 0;
@@ -137,9 +275,101 @@ __libc_recvmsg (int fd, struct msghdr *message, int flags)
message->msg_controllen = clen;
memcpy (message->msg_control, cdata, message->msg_controllen);
+ if (nports > 0)
+ {
+ newports = __alloca (nports * sizeof (mach_port_t));
+ opened_fds = __alloca (nports * sizeof (int));
+ }
+
+ /* This counts how many ports we processed completely. */
+ i = 0;
+ /* This counts how many new fds we create. */
+ newfds = 0;
+
+ for (cmsg = CMSG_FIRSTHDR (message);
+ cmsg;
+ cmsg = CMSG_NXTHDR (message, cmsg))
+ {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
+ {
+ /* SCM_RIGHTS support. */
+ /* The fd's flags are passed in the control data. */
+ int *fds = (int *) CMSG_DATA (cmsg);
+ nfds = (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
+ / sizeof (int);
+
+ for (j = 0; j < nfds; j++)
+ {
+ err = reauthenticate (ports[i], &newports[newfds]);
+ if (err)
+ goto cleanup;
+ fds[j] = opened_fds[newfds] = _hurd_intern_fd (newports[newfds],
+ fds[j], 0);
+ if (fds[j] == -1)
+ {
+ err = errno;
+ __mach_port_deallocate (__mach_task_self (), newports[newfds]);
+ goto cleanup;
+ }
+ i++;
+ newfds++;
+ }
+ }
+ else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDS)
+ {
+ /* SCM_CREDS support. */
+ /* Check received credentials */
+ struct cmsgcred *ucredp = (struct cmsgcred *) CMSG_DATA(cmsg);
+
+ err = check_auth (ports[i],
+ ucredp->cmcred_pid,
+ ucredp->cmcred_uid, ucredp->cmcred_euid,
+ ucredp->cmcred_gid,
+ ucredp->cmcred_ngroups, ucredp->cmcred_groups);
+ if (err)
+ goto cleanup;
+ i++;
+ }
+ }
+
+ for (i = 0; i < nports; i++)
+ __mach_port_deallocate (mach_task_self (), ports[i]);
+
__vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
return (buf - data);
+
+cleanup:
+ /* Clean up all the file descriptors from port 0 to i-1. */
+ if (nports > 0)
+ {
+ ii = 0;
+ newfds = 0;
+ for (cmsg = CMSG_FIRSTHDR (message);
+ cmsg;
+ cmsg = CMSG_NXTHDR (message, cmsg))
+ {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
+ {
+ nfds = (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
+ / sizeof (int);
+ for (j = 0; j < nfds && ii < i; j++, ii++, newfds++)
+ {
+ _hurd_fd_close (_hurd_fd_get (opened_fds[newfds]));
+ __mach_port_deallocate (__mach_task_self (), newports[newfds]);
+ __mach_port_deallocate (__mach_task_self (), ports[ii]);
+ }
+ }
+ else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDS)
+ {
+ __mach_port_deallocate (__mach_task_self (), ports[ii]);
+ ii++;
+ }
+ }
+ }
+
+ __vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
+ return __hurd_fail (err);
}
weak_alias (__libc_recvmsg, recvmsg)
diff --git a/sysdeps/mach/hurd/sendmsg.c b/sysdeps/mach/hurd/sendmsg.c
index d12f4a1e90..4e95d79332 100644
--- a/sysdeps/mach/hurd/sendmsg.c
+++ b/sysdeps/mach/hurd/sendmsg.c
@@ -19,11 +19,13 @@
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
+#include <unistd.h>
#include <hurd.h>
#include <hurd/fd.h>
#include <hurd/ifsock.h>
#include <hurd/socket.h>
+#include <hurd/auth_request.h>
#include "hurd/hurdsocket.h"
/* Send a message described MESSAGE on socket FD.
@@ -32,6 +34,10 @@ ssize_t
__libc_sendmsg (int fd, const struct msghdr *message, int flags)
{
error_t err = 0;
+ struct cmsghdr *cmsg;
+ mach_port_t *ports = NULL;
+ mach_msg_type_number_t nports = 0;
+ int *fds, nfds;
struct sockaddr_un *addr = message->msg_name;
socklen_t addr_len = message->msg_namelen;
addr_port_t aport = MACH_PORT_NULL;
@@ -44,6 +50,7 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
mach_msg_type_number_t len;
mach_msg_type_number_t amount;
int dealloc = 0;
+ int socketrpc = 0;
int i;
/* Find the total number of bytes to be written. */
@@ -101,6 +108,82 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
}
}
+ /* Allocate enough room for ports. */
+ cmsg = CMSG_FIRSTHDR (message);
+ for (; cmsg; cmsg = CMSG_NXTHDR ((struct msghdr *) message, cmsg))
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
+ nports += (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
+ / sizeof (int);
+ else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDS)
+ nports++;
+
+ if (nports)
+ ports = __alloca (nports * sizeof (mach_port_t));
+
+ nports = 0;
+ for (cmsg = CMSG_FIRSTHDR (message);
+ cmsg;
+ cmsg = CMSG_NXTHDR ((struct msghdr *) message, cmsg))
+ {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
+ {
+ /* SCM_RIGHTS support: send FDs. */
+ fds = (int *) CMSG_DATA (cmsg);
+ nfds = (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
+ / sizeof (int);
+
+ for (i = 0; i < nfds; i++)
+ {
+ err = HURD_DPORT_USE
+ (fds[i],
+ ({
+ err = __io_restrict_auth (port, &ports[nports],
+ 0, 0, 0, 0);
+ if (! err)
+ nports++;
+ /* We pass the flags in the control data. */
+ fds[i] = descriptor->flags;
+ err;
+ }));
+
+ if (err)
+ goto out;
+ }
+ }
+ else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDS)
+ {
+ /* SCM_CREDS support: send credentials. */
+ mach_port_t rendezvous = __mach_reply_port (), reply;
+ struct cmsgcred *ucredp;
+
+ err = __mach_port_insert_right (mach_task_self (), rendezvous,
+ rendezvous, MACH_MSG_TYPE_MAKE_SEND);
+ ports[nports++] = rendezvous;
+ if (err)
+ goto out;
+
+ ucredp = (struct cmsgcred *) CMSG_DATA(cmsg);
+ /* Fill in credentials data */
+ ucredp->cmcred_pid = __getpid();
+ ucredp->cmcred_uid = __getuid();
+ ucredp->cmcred_euid = __geteuid();
+ ucredp->cmcred_gid = __getgid();
+ ucredp->cmcred_ngroups =
+ __getgroups (sizeof (ucredp->cmcred_groups) / sizeof (gid_t),
+ ucredp->cmcred_groups);
+
+ /* And make auth server authenticate us. */
+ reply = __mach_reply_port();
+ err = __USEPORT
+ (AUTH, __auth_user_authenticate_request (port,
+ reply, MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ rendezvous, MACH_MSG_TYPE_MAKE_SEND));
+ __mach_port_deallocate (__mach_task_self (), reply);
+ if (err)
+ goto out;
+ }
+ }
+
if (addr)
{
if (addr->sun_family == AF_LOCAL)
@@ -111,9 +194,8 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
file_t file = __file_name_lookup (name, 0, 0);
if (file == MACH_PORT_NULL)
{
- if (dealloc)
- __vm_deallocate (__mach_task_self (), data.addr, len);
- return -1;
+ err = errno;
+ goto out;
}
err = __ifsock_getsockaddr (file, &aport);
__mach_port_deallocate (__mach_task_self (), file);
@@ -121,11 +203,7 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
/* The file did not grok the ifsock protocol. */
err = ENOTSOCK;
if (err)
- {
- if (dealloc)
- __vm_deallocate (__mach_task_self (), data.addr, len);
- return __hurd_fail (err);
- }
+ goto out;
}
else
err = EIEIO;
@@ -144,8 +222,9 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
/* Send the data. */
err = __socket_send (port, aport,
flags, data.ptr, len,
- NULL,
- MACH_MSG_TYPE_COPY_SEND, 0,
+ ports,
+ MACH_MSG_TYPE_COPY_SEND,
+ nports,
message->msg_control,
message->msg_controllen,
&amount);
@@ -154,11 +233,19 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
}
err;
}));
+ socketrpc = 1;
+
+ out:
+ for (i = 0; i < nports; i++)
+ __mach_port_deallocate (__mach_task_self (), ports[i]);
if (dealloc)
__vm_deallocate (__mach_task_self (), data.addr, len);
- return err ? __hurd_sockfail (fd, flags, err) : amount;
+ if (socketrpc)
+ return err ? __hurd_sockfail (fd, flags, err) : amount;
+ else
+ return __hurd_fail (err);
}
weak_alias (__libc_sendmsg, sendmsg)
diff --git a/sysdeps/mach/hurd/setegid.c b/sysdeps/mach/hurd/setegid.c
index c5e8cf622f..7b43b33b9d 100644
--- a/sysdeps/mach/hurd/setegid.c
+++ b/sysdeps/mach/hurd/setegid.c
@@ -55,6 +55,7 @@ setegid (gid_t gid)
}
__mutex_unlock (&_hurd_id.lock);
HURD_CRITICAL_END;
+ /* FIXME: handle EINTR! */
if (err)
return __hurd_fail (err);
diff --git a/sysdeps/mach/hurd/seteuid.c b/sysdeps/mach/hurd/seteuid.c
index d6001960a8..5715f9960b 100644
--- a/sysdeps/mach/hurd/seteuid.c
+++ b/sysdeps/mach/hurd/seteuid.c
@@ -55,6 +55,7 @@ seteuid (uid_t uid)
}
__mutex_unlock (&_hurd_id.lock);
HURD_CRITICAL_END;
+ /* FIXME: handle EINTR! */
if (err)
return __hurd_fail (err);
diff --git a/sysdeps/mach/hurd/setgid.c b/sysdeps/mach/hurd/setgid.c
index faac055f71..82b193bfae 100644
--- a/sysdeps/mach/hurd/setgid.c
+++ b/sysdeps/mach/hurd/setgid.c
@@ -81,6 +81,7 @@ __setgid (gid_t gid)
}
__mutex_unlock (&_hurd_id.lock);
HURD_CRITICAL_END;
+ /* FIXME: handle EINTR! */
if (err)
return __hurd_fail (err);
diff --git a/sysdeps/mach/hurd/setgroups.c b/sysdeps/mach/hurd/setgroups.c
index cdfa869fc2..ae0d631885 100644
--- a/sysdeps/mach/hurd/setgroups.c
+++ b/sysdeps/mach/hurd/setgroups.c
@@ -50,6 +50,7 @@ setgroups (size_t n, const gid_t *groups)
}
__mutex_unlock (&_hurd_id.lock);
HURD_CRITICAL_END;
+ /* FIXME: handle EINTR! */
if (err)
return __hurd_fail (err);
diff --git a/sysdeps/mach/hurd/setitimer.c b/sysdeps/mach/hurd/setitimer.c
index f5dfb7da84..9f0f34911c 100644
--- a/sysdeps/mach/hurd/setitimer.c
+++ b/sysdeps/mach/hurd/setitimer.c
@@ -103,7 +103,7 @@ timer_thread (void)
__msg_sig_post_request (_hurd_msgport,
_hurd_itimer_port,
MACH_MSG_TYPE_MAKE_SEND_ONCE,
- SIGALRM, 0, __mach_task_self ());
+ SIGALRM, SI_TIMER, __mach_task_self ());
break;
case MACH_RCV_INTERRUPTED:
@@ -128,7 +128,8 @@ timer_thread (void)
/* Forward declaration. */
static int setitimer_locked (const struct itimerval *new,
- struct itimerval *old, void *crit);
+ struct itimerval *old, void *crit,
+ int hurd_siglocked);
static sighandler_t
restart_itimer (struct hurd_signal_preemptor *preemptor,
@@ -142,7 +143,7 @@ restart_itimer (struct hurd_signal_preemptor *preemptor,
/* Either reload or disable the itimer. */
__spin_lock (&_hurd_itimer_lock);
it.it_value = it.it_interval = _hurd_itimerval.it_interval;
- setitimer_locked (&it, NULL, NULL);
+ setitimer_locked (&it, NULL, NULL, 1);
/* Continue with normal delivery (or hold, etc.) of SIGALRM. */
return SIG_ERR;
@@ -154,7 +155,7 @@ restart_itimer (struct hurd_signal_preemptor *preemptor,
static int
setitimer_locked (const struct itimerval *new, struct itimerval *old,
- void *crit)
+ void *crit, int hurd_siglocked)
{
struct itimerval newval;
struct timeval now, remaining, elapsed;
@@ -192,16 +193,19 @@ setitimer_locked (const struct itimerval *new, struct itimerval *old,
run `restart_itimer' each time a SIGALRM would arrive. */
static struct hurd_signal_preemptor preemptor =
{
- __sigmask (SIGALRM), 0, 0,
+ __sigmask (SIGALRM), SI_TIMER, SI_TIMER,
&restart_itimer,
};
- __mutex_lock (&_hurd_siglock);
+ if (!hurd_siglocked)
+ __mutex_lock (&_hurd_siglock);
if (! preemptor.next && _hurdsig_preemptors != &preemptor)
{
preemptor.next = _hurdsig_preemptors;
_hurdsig_preemptors = &preemptor;
+ _hurdsig_preempted_set |= preemptor.signals;
}
- __mutex_unlock (&_hurd_siglock);
+ if (!hurd_siglocked)
+ __mutex_unlock (&_hurd_siglock);
if (_hurd_itimer_port == MACH_PORT_NULL)
{
@@ -349,7 +353,7 @@ __setitimer (enum __itimer_which which, const struct itimerval *new,
crit = _hurd_critical_section_lock ();
__spin_lock (&_hurd_itimer_lock);
- return setitimer_locked (new, old, crit);
+ return setitimer_locked (new, old, crit, 0);
}
static void
@@ -364,7 +368,7 @@ fork_itimer (void)
it = _hurd_itimerval;
it.it_value = it.it_interval;
- setitimer_locked (&it, NULL, NULL);
+ setitimer_locked (&it, NULL, NULL, 0);
(void) &fork_itimer; /* Avoid gcc optimizing out the function. */
}
diff --git a/sysdeps/mach/hurd/setregid.c b/sysdeps/mach/hurd/setregid.c
index 45953474b7..8ebd7ff62b 100644
--- a/sysdeps/mach/hurd/setregid.c
+++ b/sysdeps/mach/hurd/setregid.c
@@ -82,6 +82,7 @@ __setregid (gid_t rgid, gid_t egid)
}
__mutex_unlock (&_hurd_id.lock);
HURD_CRITICAL_END;
+ /* FIXME: handle EINTR! */
if (err)
return __hurd_fail (err);
diff --git a/sysdeps/mach/hurd/setresgid.c b/sysdeps/mach/hurd/setresgid.c
index d09935d8b0..5c97688907 100644
--- a/sysdeps/mach/hurd/setresgid.c
+++ b/sysdeps/mach/hurd/setresgid.c
@@ -110,6 +110,7 @@ __setresgid (gid_t rgid, gid_t egid, gid_t sgid)
}
__mutex_unlock (&_hurd_id.lock);
HURD_CRITICAL_END;
+ /* FIXME: handle EINTR! */
if (err)
return __hurd_fail (err);
diff --git a/sysdeps/mach/hurd/setresuid.c b/sysdeps/mach/hurd/setresuid.c
index 3ed7dfd021..c560858c11 100644
--- a/sysdeps/mach/hurd/setresuid.c
+++ b/sysdeps/mach/hurd/setresuid.c
@@ -111,6 +111,7 @@ __setresuid (uid_t ruid, uid_t euid, uid_t suid)
__mutex_unlock (&_hurd_id.lock);
HURD_CRITICAL_END;
+ /* FIXME: handle EINTR! */
if (err)
return __hurd_fail (err);
diff --git a/sysdeps/mach/hurd/setreuid.c b/sysdeps/mach/hurd/setreuid.c
index 12548b375b..f716ddc825 100644
--- a/sysdeps/mach/hurd/setreuid.c
+++ b/sysdeps/mach/hurd/setreuid.c
@@ -82,6 +82,7 @@ __setreuid (uid_t ruid, uid_t euid)
}
__mutex_unlock (&_hurd_id.lock);
HURD_CRITICAL_END;
+ /* FIXME: handle EINTR! */
if (err)
return __hurd_fail (err);
diff --git a/sysdeps/mach/hurd/setsid.c b/sysdeps/mach/hurd/setsid.c
index 7b989361d1..35d74c9938 100644
--- a/sysdeps/mach/hurd/setsid.c
+++ b/sysdeps/mach/hurd/setsid.c
@@ -60,6 +60,7 @@ __setsid (void)
}
HURD_CRITICAL_END;
+ /* FIXME: handle EINTR! */
return err ? __hurd_fail (err) : _hurd_pgrp;
}
diff --git a/sysdeps/mach/hurd/setuid.c b/sysdeps/mach/hurd/setuid.c
index e3c0120c98..425aa60b68 100644
--- a/sysdeps/mach/hurd/setuid.c
+++ b/sysdeps/mach/hurd/setuid.c
@@ -86,6 +86,7 @@ __setuid (uid_t uid)
}
__mutex_unlock (&_hurd_id.lock);
HURD_CRITICAL_END;
+ /* FIXME: handle EINTR! */
if (err)
return __hurd_fail (err);
diff --git a/sysdeps/mach/hurd/sigaction.c b/sysdeps/mach/hurd/sigaction.c
index 5f010064c9..abf9931d6e 100644
--- a/sysdeps/mach/hurd/sigaction.c
+++ b/sysdeps/mach/hurd/sigaction.c
@@ -46,15 +46,15 @@ __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
ss = _hurd_self_sigstate ();
__spin_lock (&ss->critical_section_lock);
- __spin_lock (&ss->lock);
- old = ss->actions[sig];
+ _hurd_sigstate_lock (ss);
+ old = _hurd_sigstate_actions (ss) [sig];
if (act != NULL)
- ss->actions[sig] = a;
+ _hurd_sigstate_actions (ss) [sig] = a;
if (act != NULL && sig == SIGCHLD &&
(a.sa_flags & SA_NOCLDSTOP) != (old.sa_flags & SA_NOCLDSTOP))
{
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
/* Inform the proc server whether or not it should send us SIGCHLD for
stopped children. We do this in a critical section so that no
@@ -62,8 +62,8 @@ __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
__USEPORT (PROC,
__proc_mod_stopchild (port, !(a.sa_flags & SA_NOCLDSTOP)));
- __spin_lock (&ss->lock);
- pending = ss->pending & ~ss->blocked;
+ _hurd_sigstate_lock (ss);
+ pending = _hurd_sigstate_pending (ss) & ~ss->blocked;
}
else if (act != NULL && (a.sa_handler == SIG_IGN || a.sa_handler == SIG_DFL))
/* We are changing to an action that might be to ignore SIG signals.
@@ -72,11 +72,11 @@ __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
back and then SIG is unblocked, the signal pending now should not
arrive. So wake up the signal thread to check the new state and do
the right thing. */
- pending = ss->pending & __sigmask (sig);
+ pending = _hurd_sigstate_pending (ss) & __sigmask (sig);
else
pending = 0;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
__spin_unlock (&ss->critical_section_lock);
if (pending)
diff --git a/sysdeps/mach/hurd/sigpending.c b/sysdeps/mach/hurd/sigpending.c
index ea41ddc427..63b76bbf99 100644
--- a/sysdeps/mach/hurd/sigpending.c
+++ b/sysdeps/mach/hurd/sigpending.c
@@ -36,9 +36,9 @@ sigpending (sigset_t *set)
}
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
- pending = ss->pending;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_lock (ss);
+ pending = _hurd_sigstate_pending (ss);
+ _hurd_sigstate_unlock (ss);
*set = pending;
return 0;
diff --git a/sysdeps/mach/hurd/sigprocmask.c b/sysdeps/mach/hurd/sigprocmask.c
index e2587afcbc..5ef1bbde59 100644
--- a/sysdeps/mach/hurd/sigprocmask.c
+++ b/sysdeps/mach/hurd/sigprocmask.c
@@ -36,7 +36,7 @@ __sigprocmask (int how, const sigset_t *set, sigset_t *oset)
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
old = ss->blocked;
@@ -57,7 +57,7 @@ __sigprocmask (int how, const sigset_t *set, sigset_t *oset)
break;
default:
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
errno = EINVAL;
return -1;
}
@@ -65,9 +65,9 @@ __sigprocmask (int how, const sigset_t *set, sigset_t *oset)
ss->blocked &= ~_SIG_CANT_MASK;
}
- pending = ss->pending & ~ss->blocked;
+ pending = _hurd_sigstate_pending (ss) & ~ss->blocked;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
if (oset != NULL)
*oset = old;
diff --git a/sysdeps/mach/hurd/sigsuspend.c b/sysdeps/mach/hurd/sigsuspend.c
index 7da3897722..ca52ec5770 100644
--- a/sysdeps/mach/hurd/sigsuspend.c
+++ b/sysdeps/mach/hurd/sigsuspend.c
@@ -40,7 +40,7 @@ __sigsuspend (const sigset_t *set)
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
oldmask = ss->blocked;
if (set != NULL)
@@ -48,11 +48,11 @@ __sigsuspend (const sigset_t *set)
ss->blocked = newmask & ~_SIG_CANT_MASK;
/* Notice if any pending signals just became unblocked. */
- pending = ss->pending & ~ss->blocked;
+ pending = _hurd_sigstate_pending (ss) & ~ss->blocked;
/* Tell the signal thread to message us when a signal arrives. */
ss->suspended = wait;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
if (pending)
/* Tell the signal thread to check for pending signals. */
@@ -63,10 +63,11 @@ __sigsuspend (const sigset_t *set)
MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
__mach_port_destroy (__mach_task_self (), wait);
- __spin_lock (&ss->lock);
- ss->blocked = oldmask; /* Restore the old mask. */
- pending = ss->pending & ~ss->blocked; /* Again check for pending signals. */
- __spin_unlock (&ss->lock);
+ /* Restore the old mask and check for pending signals again. */
+ _hurd_sigstate_lock (ss);
+ ss->blocked = oldmask;
+ pending = _hurd_sigstate_pending(ss) & ~ss->blocked;
+ _hurd_sigstate_unlock (ss);
if (pending)
/* Tell the signal thread to check for pending signals. */
diff --git a/sysdeps/mach/hurd/sigwait.c b/sysdeps/mach/hurd/sigwait.c
index ce17cce895..f8e7043178 100644
--- a/sysdeps/mach/hurd/sigwait.c
+++ b/sysdeps/mach/hurd/sigwait.c
@@ -27,7 +27,7 @@ int
__sigwait (const sigset_t *set, int *sig)
{
struct hurd_sigstate *ss;
- sigset_t mask, ready;
+ sigset_t mask, ready, blocked;
int signo = 0;
struct hurd_signal_preemptor preemptor;
jmp_buf buf;
@@ -49,8 +49,8 @@ __sigwait (const sigset_t *set, int *sig)
/* Make sure this is all kosher */
assert (__sigismember (&mask, signo));
- /* Make sure this signal is unblocked */
- __sigdelset (&ss->blocked, signo);
+ /* Restore the blocking mask. */
+ ss->blocked = blocked;
return pe->handler;
}
@@ -71,10 +71,11 @@ __sigwait (const sigset_t *set, int *sig)
__sigemptyset (&mask);
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
/* See if one of these signals is currently pending. */
- __sigandset (&ready, &ss->pending, &mask);
+ sigset_t pending = _hurd_sigstate_pending (ss);
+ __sigandset (&ready, &pending, &mask);
if (! __sigisemptyset (&ready))
{
for (signo = 1; signo < NSIG; signo++)
@@ -102,7 +103,11 @@ __sigwait (const sigset_t *set, int *sig)
preemptor.next = ss->preemptors;
ss->preemptors = &preemptor;
- __spin_unlock (&ss->lock);
+ /* Unblock the expected signals */
+ blocked = ss->blocked;
+ ss->blocked &= ~mask;
+
+ _hurd_sigstate_unlock (ss);
/* Wait. */
__mach_msg (&msg, MACH_RCV_MSG, 0, sizeof (msg), wait,
@@ -113,7 +118,7 @@ __sigwait (const sigset_t *set, int *sig)
{
assert (signo);
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
/* Delete our preemptor. */
assert (ss->preemptors == &preemptor);
@@ -122,7 +127,7 @@ __sigwait (const sigset_t *set, int *sig)
all_done:
- spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
__mach_port_destroy (__mach_task_self (), wait);
*sig = signo;
diff --git a/sysdeps/mach/hurd/spawni.c b/sysdeps/mach/hurd/spawni.c
index 9351c13e56..bd7715332e 100644
--- a/sysdeps/mach/hurd/spawni.c
+++ b/sysdeps/mach/hurd/spawni.c
@@ -239,29 +239,31 @@ __spawni (pid_t *pid, const char *file,
ss = _hurd_self_sigstate ();
- assert (! __spin_lock_locked (&ss->critical_section_lock));
__spin_lock (&ss->critical_section_lock);
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
ints[INIT_SIGMASK] = ss->blocked;
- ints[INIT_SIGPENDING] = ss->pending;
+ ints[INIT_SIGPENDING] = 0;
ints[INIT_SIGIGN] = 0;
/* Unless we were asked to reset all handlers to SIG_DFL,
pass down the set of signals that were set to SIG_IGN. */
- if ((flags & POSIX_SPAWN_SETSIGDEF) == 0)
- for (i = 1; i < NSIG; ++i)
- if (ss->actions[i].sa_handler == SIG_IGN)
- ints[INIT_SIGIGN] |= __sigmask (i);
-
- /* We hold the sigstate lock until the exec has failed so that no signal
- can arrive between when we pack the blocked and ignored signals, and
- when the exec actually happens. A signal handler could change what
+ {
+ struct sigaction *actions = _hurd_sigstate_actions (ss);
+ if ((flags & POSIX_SPAWN_SETSIGDEF) == 0)
+ for (i = 1; i < NSIG; ++i)
+ if (actions[i].sa_handler == SIG_IGN)
+ ints[INIT_SIGIGN] |= __sigmask (i);
+ }
+
+ /* We hold the critical section lock until the exec has failed so that no
+ signal can arrive between when we pack the blocked and ignored signals,
+ and when the exec actually happens. A signal handler could change what
signals are blocked and ignored. Either the change will be reflected
in the exec, or the signal will never be delivered. Setting the
critical section flag avoids anything we call trying to acquire the
sigstate lock. */
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
/* Set signal mask. */
if ((flags & POSIX_SPAWN_SETSIGMASK) != 0)
@@ -370,6 +372,7 @@ __spawni (pid_t *pid, const char *file,
/* Safe to let signals happen now. */
_hurd_critical_section_unlock (ss);
+ /* FIXME: handle EINTR */
/* Execute the file actions. */
if (file_actions != NULL)
diff --git a/sysdeps/unix/bsd/unlockpt.c b/sysdeps/unix/bsd/unlockpt.c
index d771d3201e..c11ed4d23b 100644
--- a/sysdeps/unix/bsd/unlockpt.c
+++ b/sysdeps/unix/bsd/unlockpt.c
@@ -27,7 +27,7 @@
int
unlockpt (int fd)
{
- char buf[sizeof (_PATH_TTY) + 2];
+ char buf[1024]; /* XXX */
/* BSD doesn't have a lock, but it does have `revoke'. */
if (__ptsname_r (fd, buf, sizeof (buf)))
diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/unix/clock_settime.c
index 38813eddf7..3d72634a52 100644
--- a/sysdeps/unix/clock_settime.c
+++ b/sysdeps/unix/clock_settime.c
@@ -20,6 +20,9 @@
#include <sys/time.h>
#include <ldsodefs.h>
+/* TODO */
+#include <sysdeps/unix/sysv/linux/kernel-posix-cpu-timers.h>
+
#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
/* Clock frequency of the processor. We make it a 64-bit variable