summaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/aarch64/nptl/tls.h1
-rw-r--r--sysdeps/alpha/nptl/tls.h1
-rw-r--r--sysdeps/arm/nptl/tls.h1
-rw-r--r--sysdeps/generic/dl-fcntl.h21
-rw-r--r--sysdeps/generic/ldsodefs.h5
-rw-r--r--sysdeps/generic/machine-lock.h12
-rw-r--r--sysdeps/generic/machine-sp.h4
-rw-r--r--sysdeps/generic/not-cancel.h28
-rw-r--r--sysdeps/generic/symbol-hacks.h3
-rw-r--r--sysdeps/generic/thread_state.h1
-rw-r--r--sysdeps/generic/tls.h25
-rw-r--r--sysdeps/hppa/nptl/tls.h1
-rw-r--r--sysdeps/i386/atomic-machine.h107
-rw-r--r--sysdeps/i386/nptl/tls.h1
-rw-r--r--sysdeps/ia64/nptl/tls.h1
-rw-r--r--sysdeps/m68k/nptl/tls.h1
-rw-r--r--sysdeps/mach/Makefile28
-rw-r--r--sysdeps/mach/configure2
-rw-r--r--sysdeps/mach/configure.ac2
-rw-r--r--sysdeps/mach/hurd/Makefile10
-rw-r--r--sysdeps/mach/hurd/Versions4
-rw-r--r--sysdeps/mach/hurd/access.c120
-rw-r--r--sysdeps/mach/hurd/adjtime.c4
-rw-r--r--sysdeps/mach/hurd/bind.c17
-rw-r--r--sysdeps/mach/hurd/bits/errno.h8
-rw-r--r--sysdeps/mach/hurd/bits/fcntl.h15
-rw-r--r--sysdeps/mach/hurd/bits/local_lim.h9
-rw-r--r--sysdeps/mach/hurd/bits/posix_opt.h46
-rw-r--r--sysdeps/mach/hurd/bits/stat.h5
-rw-r--r--sysdeps/mach/hurd/brk.c6
-rw-r--r--sysdeps/mach/hurd/cthreads.c19
-rw-r--r--sysdeps/mach/hurd/dl-fcntl.h22
-rw-r--r--sysdeps/mach/hurd/dl-sysdep.c49
-rw-r--r--sysdeps/mach/hurd/errno-loc.c22
-rw-r--r--sysdeps/mach/hurd/errno.c1
-rw-r--r--sysdeps/mach/hurd/euidaccess.c31
-rw-r--r--sysdeps/mach/hurd/f_setlk.c68
-rw-r--r--sysdeps/mach/hurd/faccessat.c151
-rw-r--r--sysdeps/mach/hurd/fcntl.c57
-rw-r--r--sysdeps/mach/hurd/fork.c31
-rw-r--r--sysdeps/mach/hurd/ftok.c41
-rw-r--r--sysdeps/mach/hurd/ftruncate64.c34
-rw-r--r--sysdeps/mach/hurd/futimens.c79
-rw-r--r--sysdeps/mach/hurd/futimes.c26
-rw-r--r--sysdeps/mach/hurd/gai_misc.h44
-rw-r--r--sysdeps/mach/hurd/getcwd.c12
-rw-r--r--sysdeps/mach/hurd/hp-timing.h42
-rw-r--r--sysdeps/mach/hurd/i386/Makefile4
-rw-r--r--sysdeps/mach/hurd/i386/____longjmp_chk.S7
-rw-r--r--sysdeps/mach/hurd/i386/getcontext.S74
-rw-r--r--sysdeps/mach/hurd/i386/init-first.c92
-rw-r--r--sysdeps/mach/hurd/i386/makecontext.S122
-rw-r--r--sysdeps/mach/hurd/i386/setcontext.S92
-rw-r--r--sysdeps/mach/hurd/i386/sigreturn.c71
-rw-r--r--sysdeps/mach/hurd/i386/swapcontext.S110
-rw-r--r--sysdeps/mach/hurd/i386/tls.h102
-rw-r--r--sysdeps/mach/hurd/i386/tlsdesc.sym19
-rw-r--r--sysdeps/mach/hurd/i386/trampoline.c4
-rw-r--r--sysdeps/mach/hurd/i386/ucontext_i.sym29
-rw-r--r--sysdeps/mach/hurd/ifaddrs.c310
-rw-r--r--sysdeps/mach/hurd/jmp-unwind.c3
-rw-r--r--sysdeps/mach/hurd/kernel-features.h2
-rw-r--r--sysdeps/mach/hurd/libc-lock.h213
-rw-r--r--sysdeps/mach/hurd/lutimes.c21
-rw-r--r--sysdeps/mach/hurd/malloc-machine.h11
-rw-r--r--sysdeps/mach/hurd/mig-reply.c39
-rw-r--r--sysdeps/mach/hurd/openat.c2
-rw-r--r--sysdeps/mach/hurd/pipe.c21
-rw-r--r--sysdeps/mach/hurd/pipe2.c60
-rw-r--r--sysdeps/mach/hurd/profil.c10
-rw-r--r--sysdeps/mach/hurd/ptsname.c23
-rw-r--r--sysdeps/mach/hurd/reboot.c5
-rw-r--r--sysdeps/mach/hurd/recv.c8
-rw-r--r--sysdeps/mach/hurd/recvmsg.c234
-rw-r--r--sysdeps/mach/hurd/send.c4
-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.c23
-rw-r--r--sysdeps/mach/hurd/setpgid.c10
-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.c11
-rw-r--r--sysdeps/mach/hurd/setuid.c1
-rw-r--r--sysdeps/mach/hurd/shmat.c82
-rw-r--r--sysdeps/mach/hurd/shmctl.c132
-rw-r--r--sysdeps/mach/hurd/shmdt.c51
-rw-r--r--sysdeps/mach/hurd/shmget.c242
-rw-r--r--sysdeps/mach/hurd/socket.c15
-rw-r--r--sysdeps/mach/hurd/socketpair.c25
-rw-r--r--sysdeps/mach/hurd/spawni.c4
-rw-r--r--sysdeps/mach/hurd/sysdep-cancel.h9
-rw-r--r--sysdeps/mach/hurd/tls.h21
-rw-r--r--sysdeps/mach/hurd/truncate64.c (renamed from sysdeps/mach/hurd/libc-tsd.h)34
-rw-r--r--sysdeps/mach/hurd/utime-helper.c84
-rw-r--r--sysdeps/mach/hurd/utimes.c21
-rw-r--r--sysdeps/mach/i386/machine-lock.h12
-rw-r--r--sysdeps/mach/i386/thread_state.h11
-rw-r--r--sysdeps/mach/libc-lock.h201
-rw-r--r--sysdeps/mach/pagecopy.h5
-rw-r--r--sysdeps/mach/thread_state.h3
-rw-r--r--sysdeps/microblaze/nptl/tls.h1
-rw-r--r--sysdeps/mips/nptl/tls.h1
-rw-r--r--sysdeps/nios2/nptl/tls.h1
-rw-r--r--sysdeps/nptl/timer_routines.h51
-rw-r--r--sysdeps/powerpc/nptl/tls.h1
-rw-r--r--sysdeps/pthread/allocalim.h7
-rw-r--r--sysdeps/pthread/timer_routines.c31
-rw-r--r--sysdeps/s390/nptl/tls.h1
-rw-r--r--sysdeps/sh/nptl/tls.h1
-rw-r--r--sysdeps/sparc/nptl/tls.h1
-rw-r--r--sysdeps/tile/nptl/tls.h1
-rw-r--r--sysdeps/unix/bsd/unlockpt.c2
-rw-r--r--sysdeps/unix/clock_settime.c3
-rw-r--r--sysdeps/x86_64/nptl/tls.h1
119 files changed, 3186 insertions, 941 deletions
diff --git a/sysdeps/aarch64/nptl/tls.h b/sysdeps/aarch64/nptl/tls.h
index 95ea3f9a1a..1872a7d29e 100644
--- a/sysdeps/aarch64/nptl/tls.h
+++ b/sysdeps/aarch64/nptl/tls.h
@@ -119,6 +119,7 @@ typedef struct
descr->member[idx] = (value)
/* Get and set the global scope generation counter in struct pthread. */
+# define THREAD_GSCOPE_IN_TCB 1
# define THREAD_GSCOPE_FLAG_UNUSED 0
# define THREAD_GSCOPE_FLAG_USED 1
# define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/alpha/nptl/tls.h b/sysdeps/alpha/nptl/tls.h
index 90d98e124d..8a59f537ae 100644
--- a/sysdeps/alpha/nptl/tls.h
+++ b/sysdeps/alpha/nptl/tls.h
@@ -113,6 +113,7 @@ typedef struct
descr->member[idx] = (value)
/* Get and set the global scope generation counter in struct pthread. */
+#define THREAD_GSCOPE_IN_TCB 1
#define THREAD_GSCOPE_FLAG_UNUSED 0
#define THREAD_GSCOPE_FLAG_USED 1
#define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/arm/nptl/tls.h b/sysdeps/arm/nptl/tls.h
index 1ef57d2a87..0368f1a0ba 100644
--- a/sysdeps/arm/nptl/tls.h
+++ b/sysdeps/arm/nptl/tls.h
@@ -110,6 +110,7 @@ typedef struct
descr->member[idx] = (value)
/* Get and set the global scope generation counter in struct pthread. */
+#define THREAD_GSCOPE_IN_TCB 1
#define THREAD_GSCOPE_FLAG_UNUSED 0
#define THREAD_GSCOPE_FLAG_USED 1
#define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/generic/dl-fcntl.h b/sysdeps/generic/dl-fcntl.h
new file mode 100644
index 0000000000..ee3c49c203
--- /dev/null
+++ b/sysdeps/generic/dl-fcntl.h
@@ -0,0 +1,21 @@
+/* Functions with hidden attribute internal to ld.so, which are declared
+ in include/fcntl.h. Generic version.
+ Copyright (C) 2016 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/>. */
+
+extern __typeof (__open) __open attribute_hidden;
+extern __typeof (__fcntl) __fcntl attribute_hidden;
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 2733ac8268..c0a644f1cc 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -416,6 +416,9 @@ struct rtld_global
size_t count;
void *list[50];
} *_dl_scope_free_list;
+#if !THREAD_GSCOPE_IN_TCB
+ EXTERN int _dl_thread_gscope_count;
+#endif
#ifdef SHARED
};
# define __rtld_global_attribute__
@@ -509,8 +512,10 @@ struct rtld_global_ro
/* Mask for important hardware capabilities we honour. */
EXTERN uint64_t _dl_hwcap_mask;
+#ifdef HAVE_AUX_VECTOR
/* Pointer to the auxv list supplied to the program at startup. */
EXTERN ElfW(auxv_t) *_dl_auxv;
+#endif
/* Get architecture specific definitions. */
#define PROCINFO_DECL
diff --git a/sysdeps/generic/machine-lock.h b/sysdeps/generic/machine-lock.h
index 8497a7273e..140da26a7a 100644
--- a/sysdeps/generic/machine-lock.h
+++ b/sysdeps/generic/machine-lock.h
@@ -34,14 +34,21 @@ typedef volatile int __spin_lock_t;
/* Unlock LOCK. */
+extern void __spin_unlock (__spin_lock_t *__lock);
+
+#if defined __USE_EXTERN_INLINES && defined _LIBC
_EXTERN_INLINE void
__spin_unlock (__spin_lock_t *__lock)
{
*__lock = 0;
}
+#endif
/* Try to lock LOCK; return nonzero if we locked it, zero if another has. */
+extern int __spin_try_lock (__spin_lock_t *__lock);
+
+#if defined __USE_EXTERN_INLINES && defined _LIBC
_EXTERN_INLINE int
__spin_try_lock (__spin_lock_t *__lock)
{
@@ -50,14 +57,19 @@ __spin_try_lock (__spin_lock_t *__lock)
*__lock = 1;
return 1;
}
+#endif
/* Return nonzero if LOCK is locked. */
+extern int __spin_lock_locked (__spin_lock_t *__lock);
+
+#if defined __USE_EXTERN_INLINES && defined _LIBC
_EXTERN_INLINE int
__spin_lock_locked (__spin_lock_t *__lock)
{
return *__lock != 0;
}
+#endif
#endif /* machine-lock.h */
diff --git a/sysdeps/generic/machine-sp.h b/sysdeps/generic/machine-sp.h
index f7d84492f1..c1e3b2ab86 100644
--- a/sysdeps/generic/machine-sp.h
+++ b/sysdeps/generic/machine-sp.h
@@ -25,11 +25,15 @@
#define _EXTERN_INLINE __extern_inline
#endif
+extern void * __thread_stack_pointer (void);
+
+#if defined __USE_EXTERN_INLINES && defined _LIBC
_EXTERN_INLINE void *
__thread_stack_pointer (void)
{
register void *__sp__ ("{STACK-POINTER}");
return __sp__;
}
+#endif
#endif /* machine-sp.h */
diff --git a/sysdeps/generic/not-cancel.h b/sysdeps/generic/not-cancel.h
index d703bb228f..b3297107c7 100644
--- a/sysdeps/generic/not-cancel.h
+++ b/sysdeps/generic/not-cancel.h
@@ -18,10 +18,22 @@
<http://www.gnu.org/licenses/>. */
/* By default we have none. Map the name to the normal functions. */
-#define open_not_cancel(name, flags, mode) \
+
+/* Uncancelable open. */
+#if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
+# define open_not_cancel(name, flags, mode) \
__libc_open (name, flags, mode)
-#define open_not_cancel_2(name, flags) \
+# define open_not_cancel_2(name, flags) \
__libc_open (name, flags)
+#else
+/* In this case, we can't use the libc_* internal functions. */
+# define open_not_cancel(name, flags, mode) \
+ __open (name, flags, mode)
+# define open_not_cancel_2(name, flags) \
+ __open (name, flags)
+#endif
+
+/* Uncancelable openat. */
#define openat_not_cancel(fd, name, flags, mode) \
__openat (fd, name, flags, mode)
#define openat_not_cancel_3(fd, name, flags) \
@@ -30,18 +42,30 @@
__openat64 (fd, name, flags, mode)
#define openat64_not_cancel_3(fd, name, flags) \
__openat64 (fd, name, flags, 0)
+
+/* Uncancelable close. */
#define close_not_cancel(fd) \
__close (fd)
#define close_not_cancel_no_status(fd) \
(void) __close (fd)
+
+/* Uncancelable read. */
#define read_not_cancel(fd, buf, n) \
__read (fd, buf, n)
+
+/* Uncancelable write. */
#define write_not_cancel(fd, buf, n) \
__write (fd, buf, n)
+
+/* Uncancelable writev. */
#define writev_not_cancel_no_status(fd, iov, n) \
(void) __writev (fd, iov, n)
+
+/* Uncancelable fcntl. */
#define fcntl_not_cancel(fd, cmd, val) \
__fcntl (fd, cmd, val)
+
+/* Uncancelable waitpid. */
# define waitpid_not_cancel(pid, stat_loc, options) \
__waitpid (pid, stat_loc, options)
#define pause_not_cancel() \
diff --git a/sysdeps/generic/symbol-hacks.h b/sysdeps/generic/symbol-hacks.h
index ce576c9fd2..137ff57d8a 100644
--- a/sysdeps/generic/symbol-hacks.h
+++ b/sysdeps/generic/symbol-hacks.h
@@ -1,7 +1,10 @@
/* Some compiler optimizations may transform loops into memset/memmove
calls and without proper declaration it may generate PLT calls. */
#if !defined __ASSEMBLER__ && IS_IN (libc) && defined SHARED
+#include <config.h>
+# if !defined NO_HIDDEN
asm ("memmove = __GI_memmove");
asm ("memset = __GI_memset");
asm ("memcpy = __GI_memcpy");
+# endif
#endif
diff --git a/sysdeps/generic/thread_state.h b/sysdeps/generic/thread_state.h
index 07ac112691..b168e20246 100644
--- a/sysdeps/generic/thread_state.h
+++ b/sysdeps/generic/thread_state.h
@@ -22,6 +22,7 @@
/* Replace <machine> with "i386" or "mips" or whatever. */
+#define MACHINE_NEW_THREAD_STATE_FLAVOR <machine>_NEW_THREAD_STATE
#define MACHINE_THREAD_STATE_FLAVOR <machine>_THREAD_STATE
#define MACHINE_THREAD_STATE_COUNT <machine>_THREAD_STATE_COUNT
diff --git a/sysdeps/generic/tls.h b/sysdeps/generic/tls.h
index 5126a50198..7ad6438caa 100644
--- a/sysdeps/generic/tls.h
+++ b/sysdeps/generic/tls.h
@@ -71,4 +71,29 @@
This macro returns the address of the DTV of the current thread.
This normally is done using the thread register which points
to the dtv or the TCB (from which the DTV can found).
+
+
+ THREAD_GSCOPE_SET_FLAG()
+
+ This marks the current thread as currently using the global scope, and acts
+ as an acquisition memory barrier.
+
+ THREAD_GSCOPE_RESET_FLAG()
+
+ This marks the current thread as not using the global scope any more, and
+ acts as a release memory barrier before notifying THREAD_GSCOPE_WAIT().
+
+
+ THREAD_GSCOPE_WAIT()
+
+ This waits for all threads using the global scope at the moment of call to
+ stop using it, i.e. this should wait for all threads which have already
+ called THREAD_GSCOPE_SET_FLAG() to call THREAD_GSCOPE_RESET_FLAG(). This
+ also acts as a write memory barrier before waiting.
+
+
+ THREAD_GSCOPE_IN_TCB
+
+ This should be set to 1 if the global scope flag is stored within the TCB.
+ When set to 0, GL(_dl_thread_gscope_count) will be defined to store it.
*/
diff --git a/sysdeps/hppa/nptl/tls.h b/sysdeps/hppa/nptl/tls.h
index 2e0c861e09..2ac5c67a64 100644
--- a/sysdeps/hppa/nptl/tls.h
+++ b/sysdeps/hppa/nptl/tls.h
@@ -144,6 +144,7 @@ static inline void __set_cr27(struct pthread *cr27)
}
/* Get and set the global scope generation counter in struct pthread. */
+#define THREAD_GSCOPE_IN_TCB 1
#define THREAD_GSCOPE_FLAG_UNUSED 0
#define THREAD_GSCOPE_FLAG_USED 1
#define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/i386/atomic-machine.h b/sysdeps/i386/atomic-machine.h
index ce62b335af..8df4e3302d 100644
--- a/sysdeps/i386/atomic-machine.h
+++ b/sysdeps/i386/atomic-machine.h
@@ -66,35 +66,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
@@ -135,10 +126,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)) \
@@ -146,8 +135,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) \
@@ -164,18 +152,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
@@ -210,18 +195,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); \
@@ -238,7 +220,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, \
@@ -254,18 +236,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); \
@@ -283,7 +262,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)
@@ -332,18 +311,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); \
@@ -359,7 +335,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)
@@ -389,18 +365,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); \
@@ -416,7 +389,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)
@@ -487,24 +460,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)
@@ -516,18 +486,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/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h
index a6dfa9b377..54fe131fc4 100644
--- a/sysdeps/i386/nptl/tls.h
+++ b/sysdeps/i386/nptl/tls.h
@@ -439,6 +439,7 @@ tls_fill_user_desc (union user_desc_init *desc,
/* Get and set the global scope generation counter in the TCB head. */
+#define THREAD_GSCOPE_IN_TCB 1
#define THREAD_GSCOPE_FLAG_UNUSED 0
#define THREAD_GSCOPE_FLAG_USED 1
#define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/ia64/nptl/tls.h b/sysdeps/ia64/nptl/tls.h
index 54fddf5952..0a2403d8e5 100644
--- a/sysdeps/ia64/nptl/tls.h
+++ b/sysdeps/ia64/nptl/tls.h
@@ -167,6 +167,7 @@ register struct pthread *__thread_self __asm__("r13");
= THREAD_GET_POINTER_GUARD ())
/* Get and set the global scope generation counter in struct pthread. */
+#define THREAD_GSCOPE_IN_TCB 1
#define THREAD_GSCOPE_FLAG_UNUSED 0
#define THREAD_GSCOPE_FLAG_USED 1
#define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/m68k/nptl/tls.h b/sysdeps/m68k/nptl/tls.h
index f93228212b..01c1b67129 100644
--- a/sysdeps/m68k/nptl/tls.h
+++ b/sysdeps/m68k/nptl/tls.h
@@ -144,6 +144,7 @@ extern void * __m68k_read_tp (void);
# define NO_TLS_OFFSET -1
/* Get and set the global scope generation counter in struct pthread. */
+#define THREAD_GSCOPE_IN_TCB 1
#define THREAD_GSCOPE_FLAG_UNUSED 0
#define THREAD_GSCOPE_FLAG_USED 1
#define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/mach/Makefile b/sysdeps/mach/Makefile
index 7d8c67c316..244bc7b15a 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)
@@ -50,4 +50,30 @@ mach-before-compile:
before-compile += $(mach-before-compile)
endif
+ifeq (crypt,$(subdir))
+ LDLIBS-crypt.so += $(objdir)/mach/libmachuser.so
+else ifeq (dlfcn,$(subdir))
+ LDLIBS-dl.so += $(objdir)/mach/libmachuser.so
+else ifeq (nis,$(subdir))
+ LDLIBS-nsl.so += $(objdir)/mach/libmachuser.so
+ LDLIBS-nss_nis.so += $(objdir)/mach/libmachuser.so
+ LDLIBS-nss_nisplus.so += $(objdir)/mach/libmachuser.so
+ LDLIBS-nss_compat.so += $(objdir)/mach/libmachuser.so
+else ifeq (nss,$(subdir))
+ LDLIBS-nss.so += $(objdir)/mach/libmachuser.so
+ LDLIBS-nss_files.so += $(objdir)/mach/libmachuser.so
+ LDLIBS-nss_db.so += $(objdir)/mach/libmachuser.so
+ LDLIBS-nss_compat.so += $(objdir)/mach/libmachuser.so
+else ifeq (hesiod,$(subdir))
+ LDLIBS-nss_hesiod.so += $(objdir)/mach/libmachuser.so
+else ifeq (posix,$(subdir))
+ LDLIBS-tst-rfc3484 += $(objdir)/mach/libmachuser.so
+ LDLIBS-tst-rfc3484-2 += $(objdir)/mach/libmachuser.so
+ LDLIBS-tst-rfc3484-3 += $(objdir)/mach/libmachuser.so
+else ifeq (nscd,$(subdir))
+ LDLIBS-nscd += $(objdir)/mach/libmachuser.so
+endif
+
+LDLIBS-pthread.so += $(objdir)/mach/libmachuser.so
+
endif # in-Makerules
diff --git a/sysdeps/mach/configure b/sysdeps/mach/configure
index 632a9c9fa4..c6ea9be20b 100644
--- a/sysdeps/mach/configure
+++ b/sysdeps/mach/configure
@@ -282,7 +282,7 @@ if test $libc_cv_mach_task_creation_time = no; then
fi
mach_interface_list=
-for ifc in mach mach4 \
+for ifc in mach mach4 gnumach \
clock clock_priv host_priv host_security ledger lock_set \
processor processor_set task task_notify thread_act vm_map \
memory_object memory_object_default default_pager \
diff --git a/sysdeps/mach/configure.ac b/sysdeps/mach/configure.ac
index 3033fec946..cadecae884 100644
--- a/sysdeps/mach/configure.ac
+++ b/sysdeps/mach/configure.ac
@@ -59,7 +59,7 @@ dnl but we don't do a check for that here because in a bare
dnl environment the compile against those headers will fail.
dnl
mach_interface_list=
-for ifc in mach mach4 \
+for ifc in mach mach4 gnumach \
clock clock_priv host_priv host_security ledger lock_set \
processor processor_set task task_notify thread_act vm_map \
memory_object memory_object_default default_pager \
diff --git a/sysdeps/mach/hurd/Makefile b/sysdeps/mach/hurd/Makefile
index 3845c57c14..9b4ce5f5a9 100644
--- a/sysdeps/mach/hurd/Makefile
+++ b/sysdeps/mach/hurd/Makefile
@@ -79,9 +79,11 @@ endef
# the headers we want to search for Mach error codes, listed above (and
# incidentally, all other headers those include).
-include $(common-objpfx)errnos.d
-$(common-objpfx)errnos.d: $(mach-errnos-deps) libc-modules.h
+$(common-objpfx)errnos.d: $(mach-errnos-deps)
$(mach-errno-h) | \
- $(CC) $(CFLAGS) $(CPPFLAGS) -M -x c - | \
+ $(CC) $(CFLAGS) \
+ $(subst -include $(common-objpfx)libc-modules.h,,$(CPPFLAGS)) \
+ -M -x c - | \
sed $(sed-remove-objpfx) -e 's,- *:,mach-errnos-deps :=,' \
-e 's, \.\./, $(..),g' > $@t
mv -f $@t $@
@@ -192,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/Versions b/sysdeps/mach/hurd/Versions
index 89e19061af..7cab8e8551 100644
--- a/sysdeps/mach/hurd/Versions
+++ b/sysdeps/mach/hurd/Versions
@@ -6,6 +6,7 @@ libc {
GLIBC_PRIVATE {
# Functions shared with the dynamic linker
__libc_read; __libc_write; __libc_lseek64;
+ __libc_lock_self0;
_dl_init_first;
}
@@ -14,8 +15,6 @@ libc {
ld {
GLIBC_2.0 {
# variables that must be shared with libc
- __hurd_sigthread_stack_base; __hurd_sigthread_stack_end;
- __hurd_sigthread_variables;
__hurd_threadvar_stack_mask; __hurd_threadvar_stack_offset;
# functions that must be shared with libc
@@ -33,5 +32,6 @@ ld {
# functions that must be shared with libc
__libc_read; __libc_write; __libc_lseek64;
+ __libc_lock_self0;
}
}
diff --git a/sysdeps/mach/hurd/access.c b/sysdeps/mach/hurd/access.c
index c308340329..dc64183f96 100644
--- a/sysdeps/mach/hurd/access.c
+++ b/sysdeps/mach/hurd/access.c
@@ -16,131 +16,13 @@
<http://www.gnu.org/licenses/>. */
#include <unistd.h>
-#include <hurd.h>
-#include <hurd/port.h>
-#include <hurd/id.h>
-#include <hurd/lookup.h>
#include <fcntl.h>
/* Test for access to FILE by our real user and group IDs. */
int
__access (const char *file, int type)
{
- error_t err;
- file_t rcrdir, rcwdir, io;
- int flags, allowed;
-
- error_t reauthenticate (int which, file_t *result)
- {
- /* Get a port to our root directory, authenticated with the real IDs. */
- error_t err;
- mach_port_t ref;
- ref = __mach_reply_port ();
- err = HURD_PORT_USE
- (&_hurd_ports[which],
- ({
- err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND);
- if (!err)
- err = __auth_user_authenticate (_hurd_id.rid_auth,
- ref, MACH_MSG_TYPE_MAKE_SEND,
- result);
- err;
- }));
- __mach_port_destroy (__mach_task_self (), ref);
- return err;
- }
-
- error_t init_port (int which, error_t (*operate) (mach_port_t))
- {
- switch (which)
- {
- case INIT_PORT_AUTH:
- return (*operate) (_hurd_id.rid_auth);
- case INIT_PORT_CRDIR:
- return (reauthenticate (INIT_PORT_CRDIR, &rcrdir) ?:
- (*operate) (rcrdir));
- case INIT_PORT_CWDIR:
- return (reauthenticate (INIT_PORT_CWDIR, &rcwdir) ?:
- (*operate) (rcwdir));
- default:
- return _hurd_ports_use (which, operate);
- }
- }
-
- rcrdir = rcwdir = MACH_PORT_NULL;
-
- HURD_CRITICAL_BEGIN;
-
- __mutex_lock (&_hurd_id.lock);
- /* Get _hurd_id up to date. */
- if (err = _hurd_check_ids ())
- goto lose;
-
- if (_hurd_id.rid_auth == MACH_PORT_NULL)
- {
- /* Set up _hurd_id.rid_auth. This is a special auth server port
- which uses the real uid and gid (the first aux uid and gid) as
- the only effective uid and gid. */
-
- if (_hurd_id.aux.nuids < 1 || _hurd_id.aux.ngids < 1)
- {
- /* We do not have a real UID and GID. Lose, lose, lose! */
- err = EGRATUITOUS;
- goto lose;
- }
-
- /* Create a new auth port using our real UID and GID (the first
- auxiliary UID and GID) as the only effective IDs. */
- if (err = __USEPORT (AUTH,
- __auth_makeauth (port,
- NULL, MACH_MSG_TYPE_COPY_SEND, 0,
- _hurd_id.aux.uids, 1,
- _hurd_id.aux.uids,
- _hurd_id.aux.nuids,
- _hurd_id.aux.gids, 1,
- _hurd_id.aux.gids,
- _hurd_id.aux.ngids,
- &_hurd_id.rid_auth)))
- goto lose;
- }
-
- if (!err)
- /* Look up the file name using the modified init ports. */
- err = __hurd_file_name_lookup (&init_port, &__getdport, 0,
- file, 0, 0, &io);
-
- /* We are done with _hurd_id.rid_auth now. */
- lose:
- __mutex_unlock (&_hurd_id.lock);
-
- HURD_CRITICAL_END;
-
- if (rcrdir != MACH_PORT_NULL)
- __mach_port_deallocate (__mach_task_self (), rcrdir);
- if (rcwdir != MACH_PORT_NULL)
- __mach_port_deallocate (__mach_task_self (), rcwdir);
- if (err)
- return __hurd_fail (err);
-
- /* Find out what types of access we are allowed to this file. */
- err = __file_check_access (io, &allowed);
- __mach_port_deallocate (__mach_task_self (), io);
- if (err)
- return __hurd_fail (err);
-
- flags = 0;
- if (type & R_OK)
- flags |= O_READ;
- if (type & W_OK)
- flags |= O_WRITE;
- if (type & X_OK)
- flags |= O_EXEC;
-
- if (flags & ~allowed)
- /* We are not allowed all the requested types of access. */
- return __hurd_fail (EACCES);
-
- return 0;
+ return __faccessat (AT_FDCWD, file, type, 0);
}
weak_alias (__access, access)
diff --git a/sysdeps/mach/hurd/adjtime.c b/sysdeps/mach/hurd/adjtime.c
index d65b95b9c6..7cfdd53e82 100644
--- a/sysdeps/mach/hurd/adjtime.c
+++ b/sysdeps/mach/hurd/adjtime.c
@@ -28,11 +28,15 @@ __adjtime (const struct timeval *delta, struct timeval *olddelta)
{
error_t err;
mach_port_t hostpriv;
+ struct timeval dummy;
err = __get_privileged_ports (&hostpriv, NULL);
if (err)
return __hurd_fail (EPERM);
+ if (olddelta == NULL)
+ olddelta = &dummy;
+
err = __host_adjust_time (hostpriv,
/* `time_value_t' and `struct timeval' are in
fact identical with the names changed. */
diff --git a/sysdeps/mach/hurd/bind.c b/sysdeps/mach/hurd/bind.c
index e605e31c5f..7cdfefda19 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/errno.h b/sysdeps/mach/hurd/bits/errno.h
index d20ffe654a..c5db66e04e 100644
--- a/sysdeps/mach/hurd/bits/errno.h
+++ b/sysdeps/mach/hurd/bits/errno.h
@@ -222,6 +222,10 @@ enum __error_t_codes
#define ETIME _HURD_ERRNO (117)/* Timer expired */
ECANCELED = _HURD_ERRNO (119),
#define ECANCELED _HURD_ERRNO (119)/* Operation canceled */
+ EOWNERDEAD = _HURD_ERRNO (120),
+#define EOWNERDEAD _HURD_ERRNO (120)/* Robust mutex owner died */
+ ENOTRECOVERABLE = _HURD_ERRNO (121),
+#define ENOTRECOVERABLE _HURD_ERRNO (121)/* Robust mutex irrecoverable */
/* Errors from <mach/message.h>. */
EMACH_SEND_IN_PROGRESS = 0x10000001,
@@ -278,6 +282,8 @@ enum __error_t_codes
EKERN_MEMORY_PRESENT = 23,
EKERN_WRITE_PROTECTION_FAILURE = 24,
EKERN_TERMINATED = 26,
+ EKERN_TIMEDOUT = 27,
+ EKERN_INTERRUPTED = 28,
/* Errors from <mach/mig_errors.h>. */
EMIG_TYPE_ERROR = -300 /* client type check failure */,
@@ -305,7 +311,7 @@ enum __error_t_codes
};
-#define _HURD_ERRNOS 120
+#define _HURD_ERRNOS 122
/* User-visible type of error codes. It is ok to use `int' or
`kern_return_t' for these, but with `error_t' the debugger prints
diff --git a/sysdeps/mach/hurd/bits/fcntl.h b/sysdeps/mach/hurd/bits/fcntl.h
index fbd0b0abae..3f5bb96df9 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/local_lim.h b/sysdeps/mach/hurd/bits/local_lim.h
index a7760eeb1d..6222374542 100644
--- a/sysdeps/mach/hurd/bits/local_lim.h
+++ b/sysdeps/mach/hurd/bits/local_lim.h
@@ -32,3 +32,12 @@
suitable, and `sysconf' will return a number at least as large. */
#define NGROUPS_MAX 256
+
+/* The number of data keys per process. */
+#define _POSIX_THREAD_KEYS_MAX 128
+
+/* Controlling the iterations of destructors for thread-specific data. */
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
+
+/* The number of threads per process. */
+#define _POSIX_THREAD_THREADS_MAX 64
diff --git a/sysdeps/mach/hurd/bits/posix_opt.h b/sysdeps/mach/hurd/bits/posix_opt.h
index 5a578f0c1f..c4631e04f1 100644
--- a/sysdeps/mach/hurd/bits/posix_opt.h
+++ b/sysdeps/mach/hurd/bits/posix_opt.h
@@ -68,27 +68,41 @@
/* X/Open thread realtime support is not supported. */
#undef _XOPEN_REALTIME_THREADS
-/* XPG4.2 shared memory is not supported. */
-#undef _XOPEN_SHM
+/* XPG4.2 shared memory is supported. */
+#define _XOPEN_SHM 1
-/* We do not have the POSIX threads interface. */
-#define _POSIX_THREADS -1
+/* Tell we have POSIX threads. */
+#define _POSIX_THREADS 200112L
/* We have the reentrant functions described in POSIX. */
#define _POSIX_REENTRANT_FUNCTIONS 1
#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L
-/* These are all things that won't be supported when _POSIX_THREADS is not. */
+/* We do not provide priority scheduling for threads. */
#define _POSIX_THREAD_PRIORITY_SCHEDULING -1
-#define _POSIX_THREAD_ATTR_STACKSIZE -1
-#define _POSIX_THREAD_ATTR_STACKADDR -1
+
+/* We support user-defined stack sizes. */
+#define _POSIX_THREAD_ATTR_STACKSIZE 200112L
+
+/* We support user-defined stacks. */
+#define _POSIX_THREAD_ATTR_STACKADDR 200112L
+
+/* We do not support priority inheritence. */
#define _POSIX_THREAD_PRIO_INHERIT -1
+
+/* We do not support priority protection. */
#define _POSIX_THREAD_PRIO_PROTECT -1
+
#ifdef __USE_XOPEN2K8
+/* We do not support priority inheritence for robust mutexes. */
# define _POSIX_THREAD_ROBUST_PRIO_INHERIT -1
+
+/* We do not support priority protection for robust mutexes. */
# define _POSIX_THREAD_ROBUST_PRIO_PROTECT -1
#endif
-#define _POSIX_SEMAPHORES -1
+
+/* We support POSIX.1b semaphores. */
+#define _POSIX_SEMAPHORES 200112L
/* Real-time signals are not yet supported. */
#define _POSIX_REALTIME_SIGNALS -1
@@ -121,17 +135,17 @@
/* GNU libc provides regular expression handling. */
#define _POSIX_REGEXP 1
-/* Reader/Writer locks are not available. */
-#define _POSIX_READER_WRITER_LOCKS -1
+/* Reader/Writer locks are available. */
+#define _POSIX_READER_WRITER_LOCKS 200112L
/* We have a POSIX shell. */
#define _POSIX_SHELL 1
-/* We cannot support the Timeouts option without _POSIX_THREADS. */
-#define _POSIX_TIMEOUTS -1
+/* We support the Timeouts option. */
+#define _POSIX_TIMEOUTS 200112L
-/* We do not support spinlocks. */
-#define _POSIX_SPIN_LOCKS -1
+/* We support spinlocks. */
+#define _POSIX_SPIN_LOCKS 200112L
/* The `spawn' function family is supported. */
#define _POSIX_SPAWN 200809L
@@ -139,8 +153,8 @@
/* We do not have POSIX timers, but could in future without ABI change. */
#define _POSIX_TIMERS 0
-/* The barrier functions are not available. */
-#define _POSIX_BARRIERS -1
+/* We support barrier functions. */
+#define _POSIX_BARRIERS 200112L
/* POSIX message queues could be available in future. */
#define _POSIX_MESSAGE_PASSING 0
diff --git a/sysdeps/mach/hurd/bits/stat.h b/sysdeps/mach/hurd/bits/stat.h
index 3e4a7d247b..1f8bd4b3b2 100644
--- a/sysdeps/mach/hurd/bits/stat.h
+++ b/sysdeps/mach/hurd/bits/stat.h
@@ -244,6 +244,11 @@ struct stat64
# define SF_NOUNLINK 0x00100000 /* file may not be removed or renamed */
# define SF_SNAPSHOT 0x00200000 /* snapshot inode */
+#ifdef __USE_ATFILE
+# define UTIME_NOW -1 /* corresponds to the current time */
+# define UTIME_OMIT -2 /* target time is omitted */
+#endif
+
__BEGIN_DECLS
/* Set file flags for FILE to FLAGS. */
diff --git a/sysdeps/mach/hurd/brk.c b/sysdeps/mach/hurd/brk.c
index 972d6a9791..8d4307f9b7 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/cthreads.c b/sysdeps/mach/hurd/cthreads.c
index ca1cc0dd91..029cd642e0 100644
--- a/sysdeps/mach/hurd/cthreads.c
+++ b/sysdeps/mach/hurd/cthreads.c
@@ -18,11 +18,14 @@
#include <libc-lock.h>
#include <errno.h>
#include <stdlib.h>
+#include <cthreads.h>
+
+char __libc_lock_self0[0];
/* Placeholder for key creation routine from Hurd cthreads library. */
int
weak_function
-cthread_keycreate (cthread_key_t *key)
+__cthread_keycreate (cthread_key_t *key)
{
__set_errno (ENOSYS);
*key = -1;
@@ -32,7 +35,7 @@ cthread_keycreate (cthread_key_t *key)
/* Placeholder for key retrieval routine from Hurd cthreads library. */
int
weak_function
-cthread_getspecific (cthread_key_t key, void **pval)
+__cthread_getspecific (cthread_key_t key, void **pval)
{
*pval = NULL;
__set_errno (ENOSYS);
@@ -42,18 +45,8 @@ cthread_getspecific (cthread_key_t key, void **pval)
/* Placeholder for key setting routine from Hurd cthreads library. */
int
weak_function
-cthread_setspecific (cthread_key_t key, void *val)
+__cthread_setspecific (cthread_key_t key, void *val)
{
__set_errno (ENOSYS);
return -1;
}
-
-/* Call cthread_getspecific which gets a pointer to the return value instead
- of just returning it. */
-void *
-__libc_getspecific (cthread_key_t key)
-{
- void *val;
- cthread_getspecific (key, &val);
- return val;
-}
diff --git a/sysdeps/mach/hurd/dl-fcntl.h b/sysdeps/mach/hurd/dl-fcntl.h
new file mode 100644
index 0000000000..c34bf12eb1
--- /dev/null
+++ b/sysdeps/mach/hurd/dl-fcntl.h
@@ -0,0 +1,22 @@
+/* Functions with hidden attribute internal to ld.so, which are declared
+ in include/fcntl.h. Hurd version.
+ Copyright (C) 2016 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/>. */
+
+/* __open can't be hidden in ld.so on Hurd since it will be preempted by the
+ one in libc.so after bootstrap. */
+extern __typeof (__fcntl) __fcntl attribute_hidden;
diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c
index 76140cf093..c43e0c6ba1 100644
--- a/sysdeps/mach/hurd/dl-sysdep.c
+++ b/sysdeps/mach/hurd/dl-sysdep.c
@@ -62,28 +62,11 @@ rtld_hidden_data_def(__libc_stack_end)
hp_timing_t _dl_cpuclock_offset;
#endif
+/* TODO: this is never properly initialized in here. */
+void *_dl_random attribute_relro = NULL;
struct hurd_startup_data *_dl_hurd_data;
-/* This is used only within ld.so, via dl-minimal.c's __errno_location. */
-#undef errno
-int errno attribute_hidden;
-
-/* Defining these variables here avoids the inclusion of hurdsig.c. */
-unsigned long int __hurd_sigthread_stack_base;
-unsigned long int __hurd_sigthread_stack_end;
-unsigned long int *__hurd_sigthread_variables;
-
-/* Defining these variables here avoids the inclusion of init-first.c.
- We need to provide temporary storage for the per-thread variables
- of the main user thread here, since it is used for storing the
- `errno' variable. Note that this information is lost once we
- relocate the dynamic linker. */
-static unsigned long int threadvars[_HURD_THREADVAR_MAX];
-unsigned long int __hurd_threadvar_stack_offset
- = (unsigned long int) &threadvars;
-unsigned long int __hurd_threadvar_stack_mask;
-
#define FMH defined(__i386__)
#if ! FMH
# define fmh() ((void)0)
@@ -105,12 +88,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/errno-loc.c b/sysdeps/mach/hurd/errno-loc.c
index 4dca6ddca7..7709cc98ca 100644
--- a/sysdeps/mach/hurd/errno-loc.c
+++ b/sysdeps/mach/hurd/errno-loc.c
@@ -16,13 +16,21 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <errno.h>
-#include <hurd/threadvar.h>
-
-int *
+#if IS_IN (rtld)
+/*
+ * rtld can not access TLS too early, thus rtld_errno.
+ *
+ * Instead of making __open/__close pass errno from TLS to rtld_errno, simply
+ * use a weak __errno_location using rtld_errno, which will be overriden by the
+ * libc definition.
+ */
+static int rtld_errno;
+int * weak_function
__errno_location (void)
{
- return (int *) __hurd_threadvar_location (_HURD_THREADVAR_ERRNO);
+ return &rtld_errno;
}
-strong_alias (__errno_location, __hurd_errno_location)
-libc_hidden_def (__errno_location)
+libc_hidden_weak (__errno_location)
+#else
+#include <../../../csu/errno-loc.c>
+#endif
diff --git a/sysdeps/mach/hurd/errno.c b/sysdeps/mach/hurd/errno.c
deleted file mode 100644
index a29091b5e2..0000000000
--- a/sysdeps/mach/hurd/errno.c
+++ /dev/null
@@ -1 +0,0 @@
-/* No definition of `errno' variable on the Hurd. */
diff --git a/sysdeps/mach/hurd/euidaccess.c b/sysdeps/mach/hurd/euidaccess.c
index ee512ff5e3..4949aa9365 100644
--- a/sysdeps/mach/hurd/euidaccess.c
+++ b/sysdeps/mach/hurd/euidaccess.c
@@ -16,42 +16,13 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <errno.h>
-#include <stddef.h>
#include <unistd.h>
#include <fcntl.h>
-#include <hurd.h>
int
__euidaccess (const char *file, int type)
{
- error_t err;
- file_t port;
- int allowed, flags;
-
- port = __file_name_lookup (file, 0, 0);
- if (port == MACH_PORT_NULL)
- return -1;
-
- /* Find out what types of access we are allowed to this file. */
- err = __file_check_access (port, &allowed);
- __mach_port_deallocate (__mach_task_self (), port);
- if (err)
- return __hurd_fail (err);
-
- flags = 0;
- if (type & R_OK)
- flags |= O_READ;
- if (type & W_OK)
- flags |= O_WRITE;
- if (type & X_OK)
- flags |= O_EXEC;
-
- if (flags & ~allowed)
- /* We are not allowed all the requested types of access. */
- return __hurd_fail (EACCES);
-
- return 0;
+ return __faccessat (AT_FDCWD, file, type, AT_EACCESS);
}
weak_alias (__euidaccess, euidaccess)
weak_alias (__euidaccess, eaccess)
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 0a57ab627c..7eda601509 100644
--- a/sysdeps/mach/hurd/faccessat.c
+++ b/sysdeps/mach/hurd/faccessat.c
@@ -23,29 +23,153 @@
#include <sys/types.h>
#include <hurd.h>
#include <hurd/fd.h>
+#include <hurd/port.h>
+#include <hurd/id.h>
+#include <hurd/lookup.h>
int
-faccessat (int fd, const char *file, int type, int flag)
+__faccessat (int fd, const char *file, int type, int at_flags)
{
error_t err;
- file_t port;
- int allowed, flags;
+ file_t rcrdir, rcwdir, io;
+ int flags, allowed;
- if ((flag & AT_EACCESS) == 0)
+ if ((at_flags & AT_EACCESS) == AT_EACCESS)
{
- if (fd == AT_FDCWD || file[0] == '/')
- return __access (file, type);
- __set_errno (ENOTSUP); /* XXX later */
- return -1;
+ /* Use effective permissions. */
+ io = __file_name_lookup_at (fd, at_flags &~ AT_EACCESS, file, 0, 0);
+ if (io == MACH_PORT_NULL)
+ return -1;
}
+ else
+ {
+ /* We have to use real permissions instead of the
+ usual effective permissions. */
+
+ int hurd_flags = 0;
+ __hurd_at_flags (&at_flags, &hurd_flags);
+
+ error_t reauthenticate_cwdir_at (file_t *result)
+ {
+ /* Get a port to the FD directory, authenticated with the real IDs. */
+ error_t err;
+ mach_port_t ref;
+ ref = __mach_reply_port ();
+ err = HURD_DPORT_USE
+ (fd,
+ ({
+ err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND);
+ if (!err)
+ err = __auth_user_authenticate (_hurd_id.rid_auth,
+ ref, MACH_MSG_TYPE_MAKE_SEND,
+ result);
+ err;
+ }));
+ __mach_port_destroy (__mach_task_self (), ref);
+ return err;
+ }
+
+ error_t reauthenticate (int which, file_t *result)
+ {
+ /* Get a port to our root directory, authenticated with the real IDs. */
+ error_t err;
+ mach_port_t ref;
+ ref = __mach_reply_port ();
+ err = HURD_PORT_USE
+ (&_hurd_ports[which],
+ ({
+ err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND);
+ if (!err)
+ err = __auth_user_authenticate (_hurd_id.rid_auth,
+ ref, MACH_MSG_TYPE_MAKE_SEND,
+ result);
+ err;
+ }));
+ __mach_port_destroy (__mach_task_self (), ref);
+ return err;
+ }
+
+ error_t init_port (int which, error_t (*operate) (mach_port_t))
+ {
+ switch (which)
+ {
+ case INIT_PORT_AUTH:
+ return (*operate) (_hurd_id.rid_auth);
+ case INIT_PORT_CRDIR:
+ return (reauthenticate (INIT_PORT_CRDIR, &rcrdir) ?:
+ (*operate) (rcrdir));
+ case INIT_PORT_CWDIR:
+ if (fd == AT_FDCWD || file[0] == '/')
+ return (reauthenticate (INIT_PORT_CWDIR, &rcwdir) ?:
+ (*operate) (rcwdir));
+ else
+ return (reauthenticate_cwdir_at (&rcwdir) ?:
+ (*operate) (rcwdir));
+ default:
+ return _hurd_ports_use (which, operate);
+ }
+ }
+
+ rcrdir = rcwdir = MACH_PORT_NULL;
+
+ HURD_CRITICAL_BEGIN;
+
+ __mutex_lock (&_hurd_id.lock);
+ /* Get _hurd_id up to date. */
+ if (err = _hurd_check_ids ())
+ goto lose;
- port = __file_name_lookup_at (fd, flag &~ AT_EACCESS, file, 0, 0);
- if (port == MACH_PORT_NULL)
- return -1;
+ if (_hurd_id.rid_auth == MACH_PORT_NULL)
+ {
+ /* Set up _hurd_id.rid_auth. This is a special auth server port
+ which uses the real uid and gid (the first aux uid and gid) as
+ the only effective uid and gid. */
+
+ if (_hurd_id.aux.nuids < 1 || _hurd_id.aux.ngids < 1)
+ {
+ /* We do not have a real UID and GID. Lose, lose, lose! */
+ err = EGRATUITOUS;
+ goto lose;
+ }
+
+ /* Create a new auth port using our real UID and GID (the first
+ auxiliary UID and GID) as the only effective IDs. */
+ if (err = __USEPORT (AUTH,
+ __auth_makeauth (port,
+ NULL, MACH_MSG_TYPE_COPY_SEND, 0,
+ _hurd_id.aux.uids, 1,
+ _hurd_id.aux.uids,
+ _hurd_id.aux.nuids,
+ _hurd_id.aux.gids, 1,
+ _hurd_id.aux.gids,
+ _hurd_id.aux.ngids,
+ &_hurd_id.rid_auth)))
+ goto lose;
+ }
+
+ if (!err)
+ /* Look up the file name using the modified init ports. */
+ err = __hurd_file_name_lookup (&init_port, &__getdport, 0,
+ file, hurd_flags, 0, &io);
+
+ /* We are done with _hurd_id.rid_auth now. */
+ lose:
+ __mutex_unlock (&_hurd_id.lock);
+
+ HURD_CRITICAL_END;
+ /* FIXME: handle EINTR! */
+
+ if (rcrdir != MACH_PORT_NULL)
+ __mach_port_deallocate (__mach_task_self (), rcrdir);
+ if (rcwdir != MACH_PORT_NULL)
+ __mach_port_deallocate (__mach_task_self (), rcwdir);
+ if (err)
+ return __hurd_fail (err);
+ }
/* Find out what types of access we are allowed to this file. */
- err = __file_check_access (port, &allowed);
- __mach_port_deallocate (__mach_task_self (), port);
+ err = __file_check_access (io, &allowed);
+ __mach_port_deallocate (__mach_task_self (), io);
if (err)
return __hurd_fail (err);
@@ -63,3 +187,4 @@ faccessat (int fd, const char *file, int type, int flag)
return 0;
}
+weak_alias (__faccessat, faccessat)
diff --git a/sysdeps/mach/hurd/fcntl.c b/sysdeps/mach/hurd/fcntl.c
index 2898ebbb14..075b00f7b8 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 c70b0577e7..816d893373 100644
--- a/sysdeps/mach/hurd/fork.c
+++ b/sysdeps/mach/hurd/fork.c
@@ -19,6 +19,7 @@
#include <unistd.h>
#include <hurd.h>
#include <hurd/signal.h>
+#include <hurd/threadvar.h>
#include <setjmp.h>
#include <thread_state.h>
#include <sysdep.h> /* For stack growth direction. */
@@ -117,6 +118,12 @@ __fork (void)
}
__mutex_lock (&_hurd_siglock);
+ /* Acquire malloc locks. This needs to come last because fork
+ handlers may use malloc, and the libio list lock has an
+ indirect malloc dependency as well (via the getdelim
+ function). */
+ _hurd_malloc_fork_prepare ();
+
newtask = MACH_PORT_NULL;
thread = sigthread = MACH_PORT_NULL;
newproc = MACH_PORT_NULL;
@@ -505,19 +512,17 @@ __fork (void)
(natural_t *) &state, &statecount))
LOSE;
#ifdef STACK_GROWTH_UP
-#define THREADVAR_SPACE (__hurd_threadvar_max \
- * sizeof *__hurd_sightread_variables)
if (__hurd_sigthread_stack_base == 0)
{
state.SP &= __hurd_threadvar_stack_mask;
- state.SP += __hurd_threadvar_stack_offset + THREADVAR_SPACE;
+ state.SP += __hurd_threadvar_stack_offset;
}
else
state.SP = __hurd_sigthread_stack_base;
#else
if (__hurd_sigthread_stack_end == 0)
{
- /* The signal thread has a normal stack assigned by cthreads.
+ /* The signal thread has a stack assigned by cthreads.
The threadvar_stack variables conveniently tell us how
to get to the highest address in the stack, just below
the per-thread variables. */
@@ -529,6 +534,11 @@ __fork (void)
#endif
MACHINE_THREAD_STATE_SET_PC (&state,
(unsigned long int) _hurd_msgport_receive);
+
+ /* Do special thread setup for TLS if needed. */
+ if (err = _hurd_tls_fork (sigthread, _hurd_msgport_thread, &state))
+ LOSE;
+
if (err = __thread_set_state (sigthread, MACHINE_THREAD_STATE_FLAVOR,
(natural_t *) &state, statecount))
LOSE;
@@ -539,7 +549,7 @@ __fork (void)
_hurd_longjmp_thread_state (&state, env, 1);
/* Do special thread setup for TLS if needed. */
- if (err = _hurd_tls_fork (thread, &state))
+ if (err = _hurd_tls_fork (thread, ss->thread, &state))
LOSE;
if (err = __thread_set_state (thread, MACHINE_THREAD_STATE_FLAVOR,
@@ -605,6 +615,9 @@ __fork (void)
nthreads * sizeof (*threads));
}
+ /* Release malloc locks. */
+ _hurd_malloc_fork_parent ();
+
/* Run things that want to run in the parent to restore it to
normality. Usually prepare hooks and parent hooks are
symmetrical: the prepare hook arrests state in some way for the
@@ -668,8 +681,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 ();
/* Run things that want to run in the child task to set up. */
RUN_HOOK (_hurd_fork_child_hook, ());
@@ -717,6 +735,7 @@ __fork (void)
}
_hurd_critical_section_unlock (ss);
+ /* FIXME: handle EINTR */
if (!err)
{
diff --git a/sysdeps/mach/hurd/ftok.c b/sysdeps/mach/hurd/ftok.c
new file mode 100644
index 0000000000..ddd69b0dac
--- /dev/null
+++ b/sysdeps/mach/hurd/ftok.c
@@ -0,0 +1,41 @@
+/* SysV ftok for Hurd.
+ Copyright (C) 1995-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/ipc.h>
+#include <sys/stat.h>
+
+
+/* In the Hurd, we use the second-to-most-significant bit as flag for
+ private keys. We use an order of the components different from the generic
+ code in sysvipc/ftok.c so that the biggest one--the inode number--is
+ affected by this. */
+
+key_t
+ftok (const char *pathname, int proj_id)
+{
+ struct stat64 st;
+ key_t key;
+
+ if (__xstat64 (_STAT_VER, pathname, &st) < 0)
+ return (key_t) -1;
+
+ key = ((st.st_dev & 0xff) | ((proj_id & 0xff) << 8)
+ | ((st.st_ino & 0x3fff) << 16));
+
+ return key;
+}
diff --git a/sysdeps/mach/hurd/ftruncate64.c b/sysdeps/mach/hurd/ftruncate64.c
new file mode 100644
index 0000000000..53c4f64afc
--- /dev/null
+++ b/sysdeps/mach/hurd/ftruncate64.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 1991-2017 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 <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Truncate the file referenced by FD to LENGTH bytes. */
+int
+__ftruncate64 (int fd, off64_t length)
+{
+ error_t err;
+ if (err = HURD_DPORT_USE (fd, __file_set_size (port, length)))
+ return __hurd_dfail (fd, err);
+ return 0;
+}
+
+weak_alias (__ftruncate64, ftruncate64)
diff --git a/sysdeps/mach/hurd/futimens.c b/sysdeps/mach/hurd/futimens.c
new file mode 100644
index 0000000000..8810e3d0e5
--- /dev/null
+++ b/sysdeps/mach/hurd/futimens.c
@@ -0,0 +1,79 @@
+/* futimes -- change access and modification times of open file. Hurd version.
+ Copyright (C) 2002-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/time.h>
+#include <errno.h>
+#include <stddef.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Change the access time of FD to TSP[0] and
+ the modification time of FD to TSP[1]. */
+int
+__futimens (int fd, const struct timespec tsp[2])
+{
+ struct timespec atime, mtime;
+ error_t err;
+
+ if (tsp == NULL)
+ {
+ /* Setting the number of nanoseconds to UTIME_NOW tells the
+ underlying filesystems to use the current time. */
+ atime.tv_sec = 0;
+ atime.tv_nsec = UTIME_NOW;
+ mtime.tv_sec = 0;
+ mtime.tv_nsec = UTIME_NOW;
+ }
+ else
+ {
+ atime = tsp[0];
+ mtime = tsp[1];
+ }
+
+ err = HURD_DPORT_USE (fd, __file_utimens (port, atime, mtime));
+
+ if (err == MIG_BAD_ID || err == EOPNOTSUPP)
+ {
+ time_value_t atim, mtim;
+
+ if (tsp == NULL)
+ /* Setting the number of microseconds to `-1' tells the
+ underlying filesystems to use the current time. */
+ atim.microseconds = mtim.microseconds = -1;
+ else
+ {
+ if (tsp[0].tv_nsec == UTIME_NOW)
+ atim.microseconds = -1;
+ else if (tsp[0].tv_nsec == UTIME_OMIT)
+ atim.microseconds = -2;
+ else
+ TIMESPEC_TO_TIME_VALUE (&atim, &(tsp[0]));
+ if (tsp[1].tv_nsec == UTIME_NOW)
+ mtim.microseconds = -1;
+ else if (tsp[1].tv_nsec == UTIME_OMIT)
+ mtim.microseconds = -2;
+ else
+ TIMESPEC_TO_TIME_VALUE (&mtim, &(tsp[1]));
+ }
+
+ err = HURD_DPORT_USE (fd, __file_utimes (port, atim, mtim));
+ }
+
+ return err ? __hurd_dfail (fd, err) : 0;
+}
+weak_alias (__futimens, futimens)
diff --git a/sysdeps/mach/hurd/futimes.c b/sysdeps/mach/hurd/futimes.c
index a4df741a2d..a21c6adb17 100644
--- a/sysdeps/mach/hurd/futimes.c
+++ b/sysdeps/mach/hurd/futimes.c
@@ -22,29 +22,29 @@
#include <hurd.h>
#include <hurd/fd.h>
+#include "utime-helper.c"
+
/* Change the access time of FD to TVP[0] and
the modification time of FD to TVP[1]. */
int
__futimes (int fd, const struct timeval tvp[2])
{
- union tv
- {
- struct timeval tv;
- time_value_t tvt;
- };
- const union tv *u = (const union tv *) tvp;
- union tv nulltv[2];
+ struct timespec atime, mtime;
error_t err;
- if (tvp == NULL)
+ utime_ts_from_tval (tvp, &atime, &mtime);
+
+ err = HURD_DPORT_USE (fd, __file_utimens (port, atime, mtime));
+
+ if (err == EMIG_BAD_ID || err == EOPNOTSUPP)
{
- /* Setting the number of microseconds to `-1' tells the
- underlying filesystems to use the current time. */
- nulltv[0].tvt.microseconds = nulltv[1].tvt.microseconds = -1;
- u = nulltv;
+ time_value_t atim, mtim;
+
+ utime_tvalue_from_tval (tvp, &atim, &mtim);
+
+ err = HURD_DPORT_USE (fd, __file_utimes (port, atim, mtim));
}
- err = HURD_DPORT_USE (fd, __file_utimes (port, u[0].tvt, u[1].tvt));
return err ? __hurd_dfail (fd, err) : 0;
}
weak_alias (__futimes, futimes)
diff --git a/sysdeps/mach/hurd/gai_misc.h b/sysdeps/mach/hurd/gai_misc.h
new file mode 100644
index 0000000000..ee8117fa96
--- /dev/null
+++ b/sysdeps/mach/hurd/gai_misc.h
@@ -0,0 +1,44 @@
+#include <signal.h>
+#include <pthread.h>
+
+#define gai_start_notify_thread __gai_start_notify_thread
+#define gai_create_helper_thread __gai_create_helper_thread
+
+extern inline void
+__gai_start_notify_thread (void)
+{
+ sigset_t ss;
+ sigemptyset (&ss);
+ sigprocmask(SIG_SETMASK, &ss, NULL);
+}
+
+extern inline int
+__gai_create_helper_thread (pthread_t *threadp, void *(*tf) (void *),
+ void *arg)
+{
+ pthread_attr_t attr;
+
+ /* Make sure the thread is created detached. */
+ pthread_attr_init (&attr);
+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+
+ /* The helper thread needs only very little resources. */
+ (void) pthread_attr_setstacksize (&attr, 0x10000);
+
+ /* Block all signals in the helper thread. To do this thoroughly we
+ temporarily have to block all signals here. */
+ sigset_t ss;
+ sigset_t oss;
+ sigfillset (&ss);
+ sigprocmask(SIG_SETMASK, &ss, &oss);
+
+ int ret = pthread_create (threadp, &attr, tf, arg);
+
+ /* Restore the signal mask. */
+ sigprocmask(SIG_SETMASK, &oss, NULL);
+
+ (void) pthread_attr_destroy (&attr);
+ return ret;
+}
+
+#include_next <gai_misc.h>
diff --git a/sysdeps/mach/hurd/getcwd.c b/sysdeps/mach/hurd/getcwd.c
index a757dab965..d7827589d0 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;
@@ -308,13 +303,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/hp-timing.h b/sysdeps/mach/hurd/hp-timing.h
new file mode 100644
index 0000000000..1246e21958
--- /dev/null
+++ b/sysdeps/mach/hurd/hp-timing.h
@@ -0,0 +1,42 @@
+/* High precision, low overhead timing functions. Generic version.
+ Copyright (C) 1998-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ 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 _HP_TIMING_H
+#define _HP_TIMING_H 1
+
+/* We don't have support for high precision timing for now. */
+
+/* Provide dummy definitions. */
+#define HP_TIMING_AVAIL (0)
+#define HP_SMALL_TIMING_AVAIL (0)
+#define HP_TIMING_INLINE (0)
+typedef int hp_timing_t;
+#define HP_TIMING_ZERO(Var)
+#define HP_TIMING_NOW(var)
+#define HP_TIMING_DIFF_INIT()
+#define HP_TIMING_DIFF(Diff, Start, End)
+#define HP_TIMING_ACCUM(Sum, Diff)
+#define HP_TIMING_ACCUM_NT(Sum, Diff)
+#define HP_TIMING_PRINT(Buf, Len, Val)
+
+/* Since this implementation is not available we tell the user about it. */
+#define HP_TIMING_NONAVAIL 1
+
+#endif /* hp-timing.h */
diff --git a/sysdeps/mach/hurd/i386/Makefile b/sysdeps/mach/hurd/i386/Makefile
index 5f988097c2..4e326ea533 100644
--- a/sysdeps/mach/hurd/i386/Makefile
+++ b/sysdeps/mach/hurd/i386/Makefile
@@ -6,3 +6,7 @@ endif
ifeq ($(subdir),debug)
gen-as-const-headers += signal-defines.sym
endif
+
+ifeq ($(subdir),stdlib)
+gen-as-const-headers += ucontext_i.sym
+endif
diff --git a/sysdeps/mach/hurd/i386/____longjmp_chk.S b/sysdeps/mach/hurd/i386/____longjmp_chk.S
index 4ddf6cd82e..dec8ea7778 100644
--- a/sysdeps/mach/hurd/i386/____longjmp_chk.S
+++ b/sysdeps/mach/hurd/i386/____longjmp_chk.S
@@ -66,7 +66,12 @@ ENTRY (____longjmp_chk)
/* TODO: need locking? */
/* struct hurd_sigstate * _hurd_self_sigstate (void) */
- call _hurd_self_sigstate
+#ifdef PIC
+ call 1f
+1: popl %ebx
+ addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+#endif
+ call JUMPTARGET(_hurd_self_sigstate)
/* TODO: %eax and %eax->sigaltstack are always valid? */
testl $SS_ONSTACK, (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_FLAGS__OFFSET)(%eax)
diff --git a/sysdeps/mach/hurd/i386/getcontext.S b/sysdeps/mach/hurd/i386/getcontext.S
new file mode 100644
index 0000000000..8157ea420a
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/getcontext.S
@@ -0,0 +1,74 @@
+/* Save current context.
+ 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.
+
+ 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 <sysdep.h>
+
+#include "ucontext_i.h"
+
+
+ENTRY(__getcontext)
+ /* Load address of the context data structure. */
+ movl 4(%esp), %eax
+
+ /* Return value of getcontext. EAX is the only register whose
+ value is not preserved. */
+ movl $0, oEAX(%eax)
+
+ /* Save the 32-bit register values and the return address. */
+ movl %ecx, oECX(%eax)
+ movl %edx, oEDX(%eax)
+ movl %edi, oEDI(%eax)
+ movl %esi, oESI(%eax)
+ movl %ebp, oEBP(%eax)
+ movl (%esp), %ecx
+ movl %ecx, oEIP(%eax)
+ leal 4(%esp), %ecx /* Exclude the return address. */
+ movl %ecx, oESP(%eax)
+ movl %ebx, oEBX(%eax)
+
+ /* Save the FS segment register. We don't touch the GS register
+ since it is used for threads. */
+ xorl %edx, %edx
+ movw %fs, %dx
+ movl %edx, oFS(%eax)
+
+ leal oFPREGS(%eax), %ecx
+ /* Save the floating-point context. */
+ fnstenv (%ecx)
+ /* And load it right back since the processor changes the mask.
+ Intel thought this opcode to be used in interrupt handlers which
+ would block all exceptions. */
+ fldenv (%ecx)
+
+ /* Save the current signal mask. */
+ subl $12, %esp
+ cfi_adjust_cfa_offset (12)
+ leal oSIGMASK(%eax), %eax
+ movl %eax, 8(%esp)
+ movl $0, 4(%esp)
+ movl $SIG_BLOCK, (%esp)
+ call JUMPTARGET (__sigprocmask)
+ addl $12, %esp
+ cfi_adjust_cfa_offset (-12)
+ /* Propagate %eax (and errno, in case). */
+
+ ret
+PSEUDO_END(__getcontext)
+
+weak_alias (__getcontext, getcontext)
diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c
index 7a905c2435..84b81048b4 100644
--- a/sysdeps/mach/hurd/i386/init-first.c
+++ b/sysdeps/mach/hurd/i386/init-first.c
@@ -117,32 +117,10 @@ init1 (int argc, char *arg0, ...)
then after the environment pointers there is no Hurd
data block; the argument strings start there. */
if ((void *) d == argv[0])
- {
-#ifndef SHARED
- /* With a new enough linker (binutils-2.23 or better),
- the magic __ehdr_start symbol will be available and
- __libc_start_main will have done this that way already. */
- if (_dl_phdr == NULL)
- {
- /* We may need to see our own phdrs, e.g. for TLS setup.
- Try the usual kludge to find the headers without help from
- the exec server. */
- extern const void __executable_start;
- const ElfW(Ehdr) *const ehdr = &__executable_start;
- _dl_phdr = (const void *) ehdr + ehdr->e_phoff;
- _dl_phnum = ehdr->e_phnum;
- assert (ehdr->e_phentsize == sizeof (ElfW(Phdr)));
- }
-#endif
- return;
- }
+ return;
#ifndef SHARED
__libc_enable_secure = d->flags & EXEC_SECURE;
-
- _dl_phdr = (ElfW(Phdr) *) d->phdr;
- _dl_phnum = d->phdrsz / sizeof (ElfW(Phdr));
- assert (d->phdrsz % sizeof (ElfW(Phdr)) == 0);
#endif
_hurd_init_dtable = d->dtable;
@@ -177,15 +155,6 @@ init (int *data)
char **argv = (void *) (data + 1);
char **envp = &argv[argc + 1];
struct hurd_startup_data *d;
- unsigned long int threadvars[_HURD_THREADVAR_MAX];
-
- /* Provide temporary storage for thread-specific variables on the
- startup stack so the cthreads initialization code can use them
- for malloc et al, or so we can use malloc below for the real
- threadvars array. */
- memset (threadvars, 0, sizeof threadvars);
- threadvars[_HURD_THREADVAR_LOCALE] = (unsigned long int) &_nl_global_locale;
- __hurd_threadvar_stack_offset = (unsigned long int) threadvars;
/* Since the cthreads initialization code uses malloc, and the
malloc initialization code needs to get at the environment, make
@@ -198,12 +167,39 @@ init (int *data)
++envp;
d = (void *) ++envp;
- /* The user might have defined a value for this, to get more variables.
- Otherwise it will be zero on startup. We must make sure it is set
- properly before before cthreads initialization, so cthreads can know
- how much space to leave for thread variables. */
- if (__hurd_threadvar_max < _HURD_THREADVAR_MAX)
- __hurd_threadvar_max = _HURD_THREADVAR_MAX;
+#ifndef SHARED
+ /* If we are the bootstrap task started by the kernel,
+ then after the environment pointers there is no Hurd
+ data block; the argument strings start there. */
+ if ((void *) d == argv[0] || !d->phdr)
+ {
+ /* With a new enough linker (binutils-2.23 or better),
+ the magic __ehdr_start symbol will be available and
+ __libc_start_main will have done this that way already. */
+ if (_dl_phdr == NULL)
+ {
+ /* We may need to see our own phdrs, e.g. for TLS setup.
+ Try the usual kludge to find the headers without help from
+ the exec server. */
+ extern const void __executable_start;
+ const ElfW(Ehdr) *const ehdr = &__executable_start;
+ _dl_phdr = (const void *) ehdr + ehdr->e_phoff;
+ _dl_phnum = ehdr->e_phnum;
+ assert (ehdr->e_phentsize == sizeof (ElfW(Phdr)));
+ }
+ }
+ else
+ {
+ _dl_phdr = (ElfW(Phdr) *) d->phdr;
+ _dl_phnum = d->phdrsz / sizeof (ElfW(Phdr));
+ assert (d->phdrsz % sizeof (ElfW(Phdr)) == 0);
+ }
+
+ /* We need to setup TLS before starting the signal thread. */
+ extern void __pthread_initialize_minimal (void);
+ if (__pthread_initialize_minimal != NULL)
+ __pthread_initialize_minimal ();
+#endif
/* After possibly switching stacks, call `init1' (above) with the user
@@ -220,11 +216,6 @@ init (int *data)
__libc_stack_end = newsp;
- /* Copy per-thread variables from that temporary
- area onto the new cthread stack. */
- memcpy (__hurd_threadvar_location_from_sp (0, newsp),
- threadvars, sizeof threadvars);
-
/* Copy the argdata from the old stack to the new one. */
newsp = memcpy (newsp - ((char *) &d[1] - (char *) data), data,
(char *) d - (char *) data);
@@ -265,25 +256,10 @@ init (int *data)
}
else
{
- /* We are not using cthreads, so we will have just a single allocated
- area for the per-thread variables of the main user thread. */
- unsigned long int *array;
- unsigned int i;
int usercode;
void call_init1 (void);
- array = malloc (__hurd_threadvar_max * sizeof (unsigned long int));
- if (array == NULL)
- __libc_fatal ("Can't allocate single-threaded thread variables.");
-
- /* Copy per-thread variables from the temporary array into the
- newly malloc'd space. */
- memcpy (array, threadvars, sizeof threadvars);
- __hurd_threadvar_stack_offset = (unsigned long int) array;
- for (i = _HURD_THREADVAR_MAX; i < __hurd_threadvar_max; ++i)
- array[i] = 0;
-
/* The argument data is just above the stack frame we will unwind by
returning. Mutate our own return address to run the code below. */
/* The following expression would typically be written as
diff --git a/sysdeps/mach/hurd/i386/makecontext.S b/sysdeps/mach/hurd/i386/makecontext.S
new file mode 100644
index 0000000000..8364fb98ee
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/makecontext.S
@@ -0,0 +1,122 @@
+/* Create new context.
+ 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.
+
+ 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 <sysdep.h>
+
+#include "ucontext_i.h"
+
+
+ENTRY(__makecontext)
+ movl 4(%esp), %eax
+
+ /* Load the address of the function we are supposed to run. */
+ movl 8(%esp), %ecx
+
+ /* Compute the address of the stack. The information comes from
+ to us_stack element. */
+ movl oSS_SP(%eax), %edx
+ movl %ecx, oEIP(%eax)
+ addl oSS_SIZE(%eax), %edx
+
+ /* Remember the number of parameters for the exit handler since
+ it has to remove them. We store the number in the EBX register
+ which the function we will call must preserve. */
+ movl 12(%esp), %ecx
+ movl %ecx, oEBX(%eax)
+
+ /* Make room on the new stack for the parameters.
+ Room for the arguments, return address (== L(exitcode)) and
+ oLINK pointer is needed. One of the pointer sizes is subtracted
+ after aligning the stack. */
+ negl %ecx
+ leal -4(%edx,%ecx,4), %edx
+ negl %ecx
+
+ /* Align the stack. */
+ andl $0xfffffff0, %edx
+ subl $4, %edx
+
+ /* Store the future stack pointer. */
+ movl %edx, oESP(%eax)
+
+ /* Put the next context on the new stack (from the uc_link
+ element). */
+ movl oLINK(%eax), %eax
+ movl %eax, 4(%edx,%ecx,4)
+
+ /* Copy all the parameters. */
+ jecxz 2f
+1: movl 12(%esp,%ecx,4), %eax
+ movl %eax, (%edx,%ecx,4)
+ decl %ecx
+ jnz 1b
+2:
+
+ /* If the function we call returns we must continue with the
+ context which is given in the uc_link element. To do this
+ set the return address for the function the user provides
+ to a little bit of helper code which does the magic (see
+ below). */
+#ifdef PIC
+ call 1f
+ cfi_adjust_cfa_offset (4)
+1: popl %ecx
+ cfi_adjust_cfa_offset (-4)
+ addl $L(exitcode)-1b, %ecx
+ movl %ecx, (%edx)
+#else
+ movl $L(exitcode), (%edx)
+#endif
+ /* 'makecontext' returns no value. */
+ ret
+
+ /* This is the helper code which gets called if a function which
+ is registered with 'makecontext' returns. In this case we
+ have to install the context listed in the uc_link element of
+ the context 'makecontext' manipulated at the time of the
+ 'makecontext' call. If the pointer is NULL the process must
+ terminate. */
+ cfi_endproc
+L(exitcode):
+ /* This removes the parameters passed to the function given to
+ 'makecontext' from the stack. EBX contains the number of
+ parameters (see above). */
+ leal (%esp,%ebx,4), %esp
+
+#ifdef PIC
+ call 1f
+1: popl %ebx
+ addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+#endif
+ cmpl $0, (%esp) /* Check the next context. */
+ je 2f /* If it is zero exit. */
+
+ call JUMPTARGET(__setcontext)
+ /* If this returns (which can happen if the syscall fails) we'll
+ exit the program with the return error value (-1). */
+
+ movl %eax, (%esp)
+2: call HIDDEN_JUMPTARGET(exit)
+ /* The 'exit' call should never return. In case it does cause
+ the process to terminate. */
+ hlt
+ cfi_startproc
+END(__makecontext)
+
+weak_alias (__makecontext, makecontext)
diff --git a/sysdeps/mach/hurd/i386/setcontext.S b/sysdeps/mach/hurd/i386/setcontext.S
new file mode 100644
index 0000000000..8c09915dd3
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/setcontext.S
@@ -0,0 +1,92 @@
+/* Install given context.
+ 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.
+
+ 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 <sysdep.h>
+
+#include "ucontext_i.h"
+
+
+ENTRY(__setcontext)
+ /* Load address of the context data structure. */
+ movl 4(%esp), %eax
+
+ /* Get the current signal mask. */
+ subl $12, %esp
+ cfi_adjust_cfa_offset (12)
+ movl $0, 8(%esp)
+ leal oSIGMASK(%eax), %eax
+ movl %eax, 4(%esp)
+ movl $SIG_SETMASK, (%esp)
+ call JUMPTARGET (__sigprocmask)
+ addl $12, %esp
+ cfi_adjust_cfa_offset (-12)
+ testl %eax, %eax
+ jne L(pseudo_end)
+
+ /* EAX was modified, reload it. */
+ movl 4(%esp), %eax
+
+ /* Restore the floating-point context. Not the registers, only the
+ rest. */
+ leal oFPREGS(%eax), %ecx
+ fldenv (%ecx)
+
+ /* Restore the FS segment register. We don't touch the GS register
+ since it is used for threads. */
+ movl oFS(%eax), %ecx
+ movw %cx, %fs
+
+ /* Fetch the address to return to. */
+ movl oEIP(%eax), %ecx
+
+ /* Load the new stack pointer. */
+ cfi_def_cfa (eax, 0)
+ cfi_offset (edi, oEDI)
+ cfi_offset (esi, oESI)
+ cfi_offset (ebp, oEBP)
+ cfi_offset (ebx, oEBX)
+ cfi_offset (edx, oEDX)
+ cfi_offset (ecx, oECX)
+ movl oESP(%eax), %esp
+
+ /* Push the return address on the new stack so we can return there. */
+ pushl %ecx
+
+ /* Load the values of all the 32-bit registers (except ESP).
+ Since we are loading from EAX, it must be last. */
+ movl oEDI(%eax), %edi
+ movl oESI(%eax), %esi
+ movl oEBP(%eax), %ebp
+ movl oEBX(%eax), %ebx
+ movl oEDX(%eax), %edx
+ movl oECX(%eax), %ecx
+ movl oEAX(%eax), %eax
+
+ /* End FDE here, we fall into another context. */
+ cfi_endproc
+ cfi_startproc
+
+ /* The following 'ret' will pop the address of the code and jump
+ to it. */
+
+L(pseudo_end):
+ ret
+PSEUDO_END(__setcontext)
+
+weak_alias (__setcontext, setcontext)
diff --git a/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c
index 2f9c8402ca..204bd472d3 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)
{
@@ -67,18 +97,11 @@ __sigreturn (struct sigcontext *scp)
}
if (scp->sc_onstack)
- {
- ss->sigaltstack.ss_flags &= ~SS_ONSTACK; /* XXX threadvars */
- /* XXX cannot unlock until off sigstack */
- abort ();
- }
- else
- _hurd_sigstate_unlock (ss);
+ ss->sigaltstack.ss_flags &= ~SS_ONSTACK;
/* Destroy the MiG reply port used by the signal handler, and restore the
reply port in use by the thread when interrupted. */
- reply_port =
- (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY);
+ reply_port = &__hurd_local_reply_port;
if (*reply_port)
{
mach_port_t port = *reply_port;
@@ -109,27 +132,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
new file mode 100644
index 0000000000..8780572afe
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/swapcontext.S
@@ -0,0 +1,110 @@
+/* Save current context and install the given one.
+ 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.
+
+ 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 <sysdep.h>
+
+#include "ucontext_i.h"
+
+
+ENTRY(__swapcontext)
+ /* Load address of the context data structure we save in. */
+ movl 4(%esp), %eax
+
+ /* Return value of swapcontext. EAX is the only register whose
+ value is not preserved. */
+ movl $0, oEAX(%eax)
+
+ /* Save the 32-bit register values and the return address. */
+ movl %ecx, oECX(%eax)
+ movl %edx, oEDX(%eax)
+ movl %edi, oEDI(%eax)
+ movl %esi, oESI(%eax)
+ movl %ebp, oEBP(%eax)
+ movl (%esp), %ecx
+ movl %ecx, oEIP(%eax)
+ leal 4(%esp), %ecx
+ movl %ecx, oESP(%eax)
+ movl %ebx, oEBX(%eax)
+
+ /* Save the FS segment register. */
+ xorl %edx, %edx
+ movw %fs, %dx
+ movl %edx, oFS(%eax)
+
+ leal oFPREGS(%eax), %ecx
+ /* Save the floating-point context. */
+ fnstenv (%ecx)
+
+ /* Load address of the context data structure we have to load. */
+ movl 8(%esp), %ecx
+
+ /* Save the current signal mask and install the new one. */
+ subl $12, %esp
+ cfi_adjust_cfa_offset (12)
+ leal oSIGMASK(%eax), %eax
+ movl %eax, 8(%esp)
+ leal oSIGMASK(%ecx), %eax
+ movl %eax, 4(%esp)
+ movl $SIG_SETMASK, (%esp)
+ call JUMPTARGET (__sigprocmask)
+ addl $12, %esp
+ cfi_adjust_cfa_offset (-12)
+ testl %eax, %eax
+ jne L(pseudo_end)
+
+ /* EAX was modified, reload it. */
+ movl 8(%esp), %eax
+
+ /* Restore the floating-point context. Not the registers, only the
+ rest. */
+ leal oFPREGS(%eax), %ecx
+ fldenv (%ecx)
+
+ /* Restore the FS segment register. We don't touch the GS register
+ since it is used for threads. */
+ movl oFS(%eax), %edx
+ movw %dx, %fs
+
+ /* Fetch the address to return to. */
+ movl oEIP(%eax), %ecx
+
+ /* Load the new stack pointer. */
+ movl oESP(%eax), %esp
+
+ /* Push the return address on the new stack so we can return there. */
+ pushl %ecx
+
+ /* Load the values of all the 32-bit registers (except ESP).
+ Since we are loading from EAX, it must be last. */
+ movl oEDI(%eax), %edi
+ movl oESI(%eax), %esi
+ movl oEBP(%eax), %ebp
+ movl oEBX(%eax), %ebx
+ movl oEDX(%eax), %edx
+ movl oECX(%eax), %ecx
+ movl oEAX(%eax), %eax
+
+ /* The following 'ret' will pop the address of the code and jump
+ to it. */
+
+L(pseudo_end):
+ ret
+PSEUDO_END(__swapcontext)
+
+weak_alias (__swapcontext, swapcontext)
diff --git a/sysdeps/mach/hurd/i386/tls.h b/sysdeps/mach/hurd/i386/tls.h
index 3ec5bb032b..b06a1e5218 100644
--- a/sysdeps/mach/hurd/i386/tls.h
+++ b/sysdeps/mach/hurd/i386/tls.h
@@ -53,6 +53,10 @@ typedef struct
void *__private_tm[4];
/* GCC split stack support. */
void *__private_ss;
+
+ /* Keep this field last */
+ mach_port_t reply_port; /* This thread's reply port. */
+ struct hurd_sigstate *_hurd_sigstate;
} tcbhead_t;
#endif
@@ -62,6 +66,15 @@ typedef struct
#define TLS_TCB_AT_TP 1
#define TLS_DTV_AT_TP 0
+/* Alignment requirement for TCB.
+
+ Some processors such as Intel Atom pay a big penalty on every
+ access using a segment override if that segment's base is not
+ aligned to the size of a cache line. (See Intel 64 and IA-32
+ Architectures Optimization Reference Manual, section 13.3.3.3,
+ "Segment Base".) On such machines, a cache line is 64 bytes. */
+#define TCB_ALIGNMENT 64
+
#ifndef __ASSEMBLER__
/* Use i386-specific RPCs to arrange that %gs segment register prefix
@@ -72,6 +85,8 @@ typedef struct
# define __i386_set_gdt(thr, sel, desc) ((void) (thr), (void) (sel), (void) (desc), MIG_BAD_ID)
# endif
+#define __i386_selector_is_ldt(sel) (!!((sel) & 4))
+
# include <errno.h>
# include <assert.h>
@@ -88,19 +103,29 @@ typedef struct
| (((unsigned int) (tcb)) & 0xff000000) /* base 24..31 */ \
}
+# define HURD_DESC_TLS(desc) \
+ ({ \
+ (tcbhead_t *) ( (desc->low_word >> 16) \
+ | ((desc->high_word & 0xff) << 16) \
+ | (desc->high_word & 0xff000000) \
+ );})
+
+#define __LIBC_NO_TLS() \
+ ({ unsigned short ds, gs; \
+ asm ("movw %%ds,%w0; movw %%gs,%w1" : "=q" (ds), "=q" (gs)); \
+ ds == gs; })
static inline const char * __attribute__ ((unused))
_hurd_tls_init (tcbhead_t *tcb)
{
HURD_TLS_DESC_DECL (desc, tcb);
+ thread_t self = __mach_thread_self ();
+ const char *msg = NULL;
/* This field is used by TLS accesses to get our "thread pointer"
from the TLS point of view. */
tcb->tcb = tcb;
- /* Cache our thread port. */
- tcb->self = __mach_thread_self ();
-
/* Get the first available selector. */
int sel = -1;
error_t err = __i386_set_gdt (tcb->self, &sel, desc);
@@ -108,21 +133,27 @@ _hurd_tls_init (tcbhead_t *tcb)
{
/* Old kernel, use a per-thread LDT. */
sel = 0x27;
- err = __i386_set_ldt (tcb->self, sel, &desc, 1);
+ err = __i386_set_ldt (self, sel, &desc, 1);
assert_perror (err);
if (err)
- return "i386_set_ldt failed";
+ {
+ msg = "i386_set_ldt failed";
+ goto out;
+ }
}
else if (err)
{
assert_perror (err); /* Separate from above with different line #. */
- return "i386_set_gdt failed";
+ msg = "i386_set_gdt failed";
+ goto out;
}
/* Now install the new selector. */
asm volatile ("mov %w0, %%gs" :: "q" (sel));
- return 0;
+out:
+ __mach_port_deallocate (__mach_task_self (), self);
+ return msg;
}
/* Code to initially initialize the thread pointer. This might need
@@ -138,6 +169,20 @@ _hurd_tls_init (tcbhead_t *tcb)
: "i" (offsetof (tcbhead_t, tcb))); \
__tcb;})
+/* Return the TCB address of a thread given its state. */
+# define THREAD_TCB(thread, thread_state) \
+ ({ int __sel = (thread_state)->basic.gs; \
+ struct descriptor __desc, *___desc = &__desc; \
+ unsigned int __count = 1; \
+ kern_return_t __err; \
+ if (__builtin_expect (__sel, 0x48) & 4) /* LDT selector */ \
+ __err = __i386_get_ldt ((thread), __sel, 1, &___desc, &__count); \
+ else \
+ __err = __i386_get_gdt ((thread), __sel, &__desc); \
+ assert_perror (__err); \
+ assert (__count == 1); \
+ HURD_DESC_TLS(___desc);})
+
/* Install new dtv for current thread. */
# define INSTALL_NEW_DTV(dtvp) \
({ asm volatile ("movl %0,%%gs:%P1" \
@@ -151,9 +196,40 @@ _hurd_tls_init (tcbhead_t *tcb)
# include <mach/machine/thread_status.h>
-/* Set up TLS in the new thread of a fork child, copying from our own. */
-static inline error_t __attribute__ ((unused))
-_hurd_tls_fork (thread_t child, struct i386_thread_state *state)
+/* Set up TLS in the new thread of a fork child, copying from the original. */
+static inline kern_return_t __attribute__ ((unused))
+_hurd_tls_fork (thread_t child, thread_t orig, struct i386_thread_state *state)
+{
+ /* Fetch the selector set by _hurd_tls_init. */
+ int sel;
+ asm ("mov %%gs, %w0" : "=q" (sel) : "0" (0));
+ if (sel == state->ds) /* _hurd_tls_init was never called. */
+ return 0;
+
+ struct descriptor desc, *_desc = &desc;
+ error_t err;
+ unsigned int count = 1;
+
+ if (__glibc_unlikely (__i386_selector_is_ldt(sel)))
+ err = __i386_get_ldt (orig, sel, 1, &_desc, &count);
+ else
+ err = __i386_get_gdt (orig, sel, &desc);
+
+ assert_perror (err);
+ if (err)
+ return err;
+
+ if (__glibc_unlikely (__i386_selector_is_ldt(sel)))
+ err = __i386_set_ldt (child, sel, &desc, 1);
+ else
+ err = __i386_set_gdt (child, &sel, desc);
+
+ state->gs = sel;
+ return err;
+}
+
+static inline kern_return_t __attribute__ ((unused))
+_hurd_tls_new (thread_t child, struct i386_thread_state *state, tcbhead_t *tcb)
{
/* Fetch the selector set by _hurd_tls_init. */
int sel;
@@ -161,11 +237,13 @@ _hurd_tls_fork (thread_t child, struct i386_thread_state *state)
if (sel == state->ds) /* _hurd_tls_init was never called. */
return 0;
- tcbhead_t *const tcb = THREAD_SELF;
HURD_TLS_DESC_DECL (desc, tcb);
error_t err;
- if (__builtin_expect (sel, 0x50) & 4) /* LDT selector */
+ tcb->tcb = tcb;
+ tcb->self = child;
+
+ if (__glibc_unlikely (__i386_selector_is_ldt(sel)))
err = __i386_set_ldt (child, sel, &desc, 1);
else
err = __i386_set_gdt (child, &sel, desc);
diff --git a/sysdeps/mach/hurd/i386/tlsdesc.sym b/sysdeps/mach/hurd/i386/tlsdesc.sym
new file mode 100644
index 0000000000..a358f7e325
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/tlsdesc.sym
@@ -0,0 +1,19 @@
+#include <stddef.h>
+#include <sysdep.h>
+#include <tls.h>
+#include <link.h>
+#include <dl-tlsdesc.h>
+
+--
+
+-- We have to override sysdeps/i386/tlsdesc.sym to adapt to our libpthread.
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+
+DTV_OFFSET offsetof(tcbhead_t, dtv)
+
+TLSDESC_ARG offsetof(struct tlsdesc, arg)
+
+TLSDESC_GEN_COUNT offsetof(struct tlsdesc_dynamic_arg, gen_count)
+TLSDESC_MODID offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_module)
+TLSDESC_MODOFF offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_offset)
diff --git a/sysdeps/mach/hurd/i386/trampoline.c b/sysdeps/mach/hurd/i386/trampoline.c
index d694460ef3..2ff3c406c5 100644
--- a/sysdeps/mach/hurd/i386/trampoline.c
+++ b/sysdeps/mach/hurd/i386/trampoline.c
@@ -139,7 +139,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
sizeof (state->basic));
memcpy (&state->fpu, &ss->context->sc_i386_float_state,
sizeof (state->fpu));
- state->set |= (1 << i386_THREAD_STATE) | (1 << i386_FLOAT_STATE);
+ state->set |= (1 << i386_REGS_SEGS_STATE) | (1 << i386_FLOAT_STATE);
}
}
@@ -164,8 +164,6 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
{
sigsp = ss->sigaltstack.ss_sp + ss->sigaltstack.ss_size;
ss->sigaltstack.ss_flags |= SS_ONSTACK;
- /* XXX need to set up base of new stack for
- per-thread variables, cthreads. */
}
/* This code has intimate knowledge of the special mach_msg system call
done in intr-msg.c; that code does (see intr-msg.h):
diff --git a/sysdeps/mach/hurd/i386/ucontext_i.sym b/sysdeps/mach/hurd/i386/ucontext_i.sym
new file mode 100644
index 0000000000..cc1cfd578d
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/ucontext_i.sym
@@ -0,0 +1,29 @@
+#include <stddef.h>
+#include <signal.h>
+#include <sys/ucontext.h>
+
+--
+
+SIG_BLOCK
+SIG_SETMASK
+
+#define ucontext(member) offsetof (ucontext_t, member)
+#define mcontext(member) ucontext (uc_mcontext.member)
+#define mreg(reg) mcontext (gregs[REG_##reg])
+
+oLINK ucontext (uc_link)
+oSS_SP ucontext (uc_stack.ss_sp)
+oSS_SIZE ucontext (uc_stack.ss_size)
+oGS mreg (GS)
+oFS mreg (FS)
+oEDI mreg (EDI)
+oESI mreg (ESI)
+oEBP mreg (EBP)
+oESP mreg (ESP)
+oEBX mreg (EBX)
+oEDX mreg (EDX)
+oECX mreg (ECX)
+oEAX mreg (EAX)
+oEIP mreg (EIP)
+oFPREGS mcontext (fpregs)
+oSIGMASK ucontext (uc_sigmask)
diff --git a/sysdeps/mach/hurd/ifaddrs.c b/sysdeps/mach/hurd/ifaddrs.c
new file mode 100644
index 0000000000..a07bd97715
--- /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 f74124eea9..ea8b4b7082 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/kernel-features.h b/sysdeps/mach/hurd/kernel-features.h
index 7de5c11b66..d5fdf3edf9 100644
--- a/sysdeps/mach/hurd/kernel-features.h
+++ b/sysdeps/mach/hurd/kernel-features.h
@@ -23,3 +23,5 @@
#define __ASSUME_O_CLOEXEC 1
#define __ASSUME_DUP3 1
#define __ASSUME_ACCEPT4 1
+#define __ASSUME_SOCK_CLOEXEC 1
+#define __ASSUME_PIPE2 1
diff --git a/sysdeps/mach/hurd/libc-lock.h b/sysdeps/mach/hurd/libc-lock.h
deleted file mode 100644
index f6cbe50fc2..0000000000
--- a/sysdeps/mach/hurd/libc-lock.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/* libc-internal interface for mutex locks. Hurd version using Mach cthreads.
- Copyright (C) 1996-2016 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/>. */
-
-#ifndef _LIBC_LOCK_H
-#define _LIBC_LOCK_H 1
-
-#if (_LIBC - 0) || (_CTHREADS_ - 0)
-#include <cthreads.h>
-#include <hurd/threadvar.h>
-
-typedef struct mutex __libc_lock_t;
-typedef struct
-{
- struct mutex mutex;
- void *owner;
- int count;
-} __libc_lock_recursive_t;
-typedef __libc_lock_recursive_t __rtld_lock_recursive_t;
-
-#define __libc_lock_owner_self() ((void *) __hurd_threadvar_location (0))
-
-#else
-typedef struct __libc_lock_opaque__ __libc_lock_t;
-typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
-#endif
-
-/* Define a lock variable NAME with storage class CLASS. The lock must be
- initialized with __libc_lock_init before it can be used (or define it
- with __libc_lock_define_initialized, below). Use `extern' for CLASS to
- declare a lock defined in another module. In public structure
- definitions you must use a pointer to the lock structure (i.e., NAME
- begins with a `*'), because its storage size will not be known outside
- of libc. */
-#define __libc_lock_define(CLASS,NAME) \
- CLASS __libc_lock_t NAME;
-
-/* Define an initialized lock variable NAME with storage class CLASS. */
-#define _LIBC_LOCK_INITIALIZER MUTEX_INITIALIZER
-#define __libc_lock_define_initialized(CLASS,NAME) \
- CLASS __libc_lock_t NAME = _LIBC_LOCK_INITIALIZER;
-
-/* Initialize the named lock variable, leaving it in a consistent, unlocked
- state. */
-#define __libc_lock_init(NAME) __mutex_init (&(NAME))
-
-/* Finalize the named lock variable, which must be locked. It cannot be
- used again until __libc_lock_init is called again on it. This must be
- called on a lock variable before the containing storage is reused. */
-#define __libc_lock_fini(NAME) __mutex_unlock (&(NAME))
-#define __libc_lock_fini_recursive(NAME) __mutex_unlock (&(NAME).mutex)
-#define __rtld_lock_fini_recursive(NAME) __mutex_unlock (&(NAME).mutex)
-
-
-/* Lock the named lock variable. */
-#define __libc_lock_lock(NAME) __mutex_lock (&(NAME))
-
-/* Lock the named lock variable. */
-#define __libc_lock_trylock(NAME) (!__mutex_trylock (&(NAME)))
-
-/* Unlock the named lock variable. */
-#define __libc_lock_unlock(NAME) __mutex_unlock (&(NAME))
-
-
-#define __libc_lock_define_recursive(CLASS,NAME) \
- CLASS __libc_lock_recursive_t NAME;
-#define _LIBC_LOCK_RECURSIVE_INITIALIZER { MUTEX_INITIALIZER, 0, 0 }
-#define __libc_lock_define_initialized_recursive(CLASS,NAME) \
- CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
-
-#define __rtld_lock_define_recursive(CLASS,NAME) \
- __libc_lock_define_recursive (CLASS, NAME)
-#define _RTLD_LOCK_RECURSIVE_INITIALIZER \
- _LIBC_LOCK_RECURSIVE_INITIALIZER
-#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
- __libc_lock_define_initialized_recursive (CLASS, NAME)
-
-#define __libc_lock_init_recursive(NAME) \
- ({ __libc_lock_recursive_t *const __lock = &(NAME); \
- __lock->owner = 0; mutex_init (&__lock->mutex); })
-
-#define __libc_lock_trylock_recursive(NAME) \
- ({ __libc_lock_recursive_t *const __lock = &(NAME); \
- void *__self = __libc_lock_owner_self (); \
- __mutex_trylock (&__lock->mutex) \
- ? (__lock->owner = __self, __lock->count = 1, 0) \
- : __lock->owner == __self ? (++__lock->count, 0) : 1; })
-
-#define __libc_lock_lock_recursive(NAME) \
- ({ __libc_lock_recursive_t *const __lock = &(NAME); \
- void *__self = __libc_lock_owner_self (); \
- if (__mutex_trylock (&__lock->mutex) \
- || (__lock->owner != __self \
- && (__mutex_lock (&__lock->mutex), 1))) \
- __lock->owner = __self, __lock->count = 1; \
- else \
- ++__lock->count; \
- })
-#define __libc_lock_unlock_recursive(NAME) \
- ({ __libc_lock_recursive_t *const __lock = &(NAME); \
- if (--__lock->count == 0) \
- { \
- __lock->owner = 0; \
- __mutex_unlock (&__lock->mutex); \
- } \
- })
-
-
-#define __rtld_lock_initialize(NAME) \
- (void) ((NAME) = (__rtld_lock_recursive_t) _RTLD_LOCK_RECURSIVE_INITIALIZER)
-#define __rtld_lock_trylock_recursive(NAME) \
- __libc_lock_trylock_recursive (NAME)
-#define __rtld_lock_lock_recursive(NAME) \
- __libc_lock_lock_recursive(NAME)
-#define __rtld_lock_unlock_recursive(NAME) \
- __libc_lock_unlock_recursive (NAME)
-
-
-/* XXX for now */
-#define __libc_rwlock_define __libc_lock_define
-#define __libc_rwlock_define_initialized __libc_lock_define_initialized
-#define __libc_rwlock_init __libc_lock_init
-#define __libc_rwlock_fini __libc_lock_fini
-#define __libc_rwlock_rdlock __libc_lock_lock
-#define __libc_rwlock_wrlock __libc_lock_lock
-#define __libc_rwlock_tryrdlock __libc_lock_trylock
-#define __libc_rwlock_trywrlock __libc_lock_trylock
-#define __libc_rwlock_unlock __libc_lock_unlock
-
-
-/* Start a critical region with a cleanup function */
-#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
-{ \
- typeof (***(FCT)) *__save_FCT = (DOIT) ? (FCT) : 0; \
- typeof (ARG) __save_ARG = ARG; \
- /* close brace is in __libc_cleanup_region_end below. */
-
-/* End a critical region started with __libc_cleanup_region_start. */
-#define __libc_cleanup_region_end(DOIT) \
- if ((DOIT) && __save_FCT != 0) \
- (*__save_FCT)(__save_ARG); \
-}
-
-/* Sometimes we have to exit the block in the middle. */
-#define __libc_cleanup_end(DOIT) \
- if ((DOIT) && __save_FCT != 0) \
- (*__save_FCT)(__save_ARG); \
-
-#define __libc_cleanup_push(fct, arg) __libc_cleanup_region_start (1, fct, arg)
-#define __libc_cleanup_pop(execute) __libc_cleanup_region_end (execute)
-
-#if (_CTHREADS_ - 0)
-
-/* Use mutexes as once control variables. */
-
-struct __libc_once
- {
- __libc_lock_t lock;
- int done;
- };
-
-#define __libc_once_define(CLASS,NAME) \
- CLASS struct __libc_once NAME = { MUTEX_INITIALIZER, 0 }
-
-/* Call handler iff the first call. */
-#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
- do { \
- __libc_lock_lock (ONCE_CONTROL.lock); \
- if (!ONCE_CONTROL.done) \
- (INIT_FUNCTION) (); \
- ONCE_CONTROL.done = 1; \
- __libc_lock_unlock (ONCE_CONTROL.lock); \
- } while (0)
-
-/* Get once control variable. */
-#define __libc_once_get(ONCE_CONTROL) ((ONCE_CONTROL).done != 0)
-
-#ifdef _LIBC
-/* We need portable names for some functions. E.g., when they are
- used as argument to __libc_cleanup_region_start. */
-#define __libc_mutex_unlock __mutex_unlock
-#endif
-
-/* Type for key of thread specific data. */
-typedef cthread_key_t __libc_key_t;
-
-#define __libc_key_create(KEY,DEST) cthread_keycreate (KEY)
-#define __libc_setspecific(KEY,VAL) cthread_setspecific (KEY, VAL)
-void *__libc_getspecific (__libc_key_t key);
-
-#endif /* _CTHREADS_ */
-
-/* Hide the definitions which are only supposed to be used inside libc in
- a separate file. This file is not present in the installation! */
-#ifdef _LIBC
-# include <libc-lockP.h>
-#endif
-
-#endif /* libc-lock.h */
diff --git a/sysdeps/mach/hurd/lutimes.c b/sysdeps/mach/hurd/lutimes.c
index d39e4e7271..89d5226335 100644
--- a/sysdeps/mach/hurd/lutimes.c
+++ b/sysdeps/mach/hurd/lutimes.c
@@ -22,33 +22,22 @@
#include <hurd.h>
#include <fcntl.h>
+#include "utime-helper.c"
+
/* Change the access time of FILE to TVP[0] and
the modification time of FILE to TVP[1]. */
int
__lutimes (const char *file, const struct timeval tvp[2])
{
- union tv
- {
- struct timeval tv;
- time_value_t tvt;
- };
- const union tv *u = (const union tv *) tvp;
- union tv nulltv[2];
error_t err;
file_t port;
- if (tvp == NULL)
- {
- /* Setting the number of microseconds to `-1' tells the
- underlying filesystems to use the current time. */
- nulltv[0].tvt.microseconds = nulltv[1].tvt.microseconds = -1;
- u = nulltv;
- }
-
port = __file_name_lookup (file, O_NOLINK, 0);
if (port == MACH_PORT_NULL)
return -1;
- err = __file_utimes (port, u[0].tvt, u[1].tvt);
+
+ err = hurd_futimens (port, tvp);
+
__mach_port_deallocate (__mach_task_self (), port);
if (err)
return __hurd_fail (err);
diff --git a/sysdeps/mach/hurd/malloc-machine.h b/sysdeps/mach/hurd/malloc-machine.h
index 515f3ff151..d3580059a6 100644
--- a/sysdeps/mach/hurd/malloc-machine.h
+++ b/sysdeps/mach/hurd/malloc-machine.h
@@ -22,15 +22,14 @@
#undef thread_atfork_static
-#include <atomic.h>
#include <libc-lock.h>
+#include <mach/lock-intern.h>
-/* Assume hurd, with cthreads */
-
-/* Cthreads `mutex_t' is a pointer to a mutex, and malloc wants just the
- mutex itself. */
#undef mutex_t
-#define mutex_t struct mutex
+#define mutex_t unsigned int
+
+#undef MUTEX_INITIALIZER
+#define MUTEX_INITIALIZER LLL_INITIALIZER
#undef mutex_init
#define mutex_init(m) ({ __mutex_init(m); 0; })
diff --git a/sysdeps/mach/hurd/mig-reply.c b/sysdeps/mach/hurd/mig-reply.c
index 5471cf220d..5aa04a8389 100644
--- a/sysdeps/mach/hurd/mig-reply.c
+++ b/sysdeps/mach/hurd/mig-reply.c
@@ -18,26 +18,20 @@
#include <mach.h>
#include <hurd/threadvar.h>
-#define GETPORT \
- mach_port_t *portloc = \
- (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY)
-#define reply_port (*(use_threadvar ? portloc : &global_reply_port))
-
-static int use_threadvar;
-static mach_port_t global_reply_port;
-
/* These functions are called by MiG-generated code. */
+mach_port_t __hurd_reply_port0;
+
/* Called by MiG to get a reply port. */
mach_port_t
__mig_get_reply_port (void)
{
- GETPORT;
-
- if (reply_port == MACH_PORT_NULL)
- reply_port = __mach_reply_port ();
+ if (__hurd_local_reply_port == MACH_PORT_NULL ||
+ (&__hurd_local_reply_port != &__hurd_reply_port0
+ && __hurd_local_reply_port == __hurd_reply_port0))
+ __hurd_local_reply_port = __mach_reply_port ();
- return reply_port;
+ return __hurd_local_reply_port;
}
weak_alias (__mig_get_reply_port, mig_get_reply_port)
@@ -45,12 +39,8 @@ weak_alias (__mig_get_reply_port, mig_get_reply_port)
void
__mig_dealloc_reply_port (mach_port_t arg)
{
- mach_port_t port;
-
- GETPORT;
-
- port = reply_port;
- reply_port = MACH_PORT_NULL; /* So the mod_refs RPC won't use it. */
+ mach_port_t port = __hurd_local_reply_port;
+ __hurd_local_reply_port = MACH_PORT_NULL; /* So the mod_refs RPC won't use it. */
if (MACH_PORT_VALID (port))
__mach_port_mod_refs (__mach_task_self (), port,
@@ -73,15 +63,6 @@ weak_alias (__mig_put_reply_port, mig_put_reply_port)
void
__mig_init (void *stack)
{
- use_threadvar = stack != 0;
-
- if (use_threadvar)
- {
- /* Recycle the reply port used before multithreading was enabled. */
- mach_port_t *portloc = (mach_port_t *)
- __hurd_threadvar_location_from_sp (_HURD_THREADVAR_MIG_REPLY, stack);
- *portloc = global_reply_port;
- global_reply_port = MACH_PORT_NULL;
- }
+ /* Do nothing. */
}
weak_alias (__mig_init, mig_init)
diff --git a/sysdeps/mach/hurd/openat.c b/sysdeps/mach/hurd/openat.c
index 974ff3fa15..4bb6ae421a 100644
--- a/sysdeps/mach/hurd/openat.c
+++ b/sysdeps/mach/hurd/openat.c
@@ -29,7 +29,7 @@
the directory associated with FD. If O_CREAT or O_TMPFILE is in OFLAG, a
third argument is the file protection. */
int
-__openat (int fd, const char *file, int oflag)
+__openat (int fd, const char *file, int oflag, ...)
{
mode_t mode;
io_t port;
diff --git a/sysdeps/mach/hurd/pipe.c b/sysdeps/mach/hurd/pipe.c
index 364c856a59..d4194bbe62 100644
--- a/sysdeps/mach/hurd/pipe.c
+++ b/sysdeps/mach/hurd/pipe.c
@@ -15,9 +15,6 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <errno.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
#include <unistd.h>
/* Create a one-way communication channel (pipe).
@@ -28,23 +25,7 @@
int
__pipe (int fds[2])
{
- int save_errno = errno;
- int result;
-
- /* The magic S_IFIFO protocol tells the pflocal server to create
- sockets which report themselves as FIFOs, as POSIX requires for
- pipes. */
- result = __socketpair (PF_LOCAL, SOCK_STREAM, S_IFIFO, fds);
- if (result == -1 && errno == EPROTONOSUPPORT)
- {
- /* We contacted an "old" pflocal server that doesn't support the
- magic S_IFIFO protocol.
- FIXME: Remove this junk somewhere in the future. */
- __set_errno (save_errno);
- return __socketpair (PF_LOCAL, SOCK_STREAM, 0, fds);
- }
-
- return result;
+ return __pipe2 (fds, 0);
}
libc_hidden_def (__pipe)
weak_alias (__pipe, pipe)
diff --git a/sysdeps/mach/hurd/pipe2.c b/sysdeps/mach/hurd/pipe2.c
new file mode 100644
index 0000000000..8086d64724
--- /dev/null
+++ b/sysdeps/mach/hurd/pipe2.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 1992-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 <errno.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <fcntl-internal.h>
+#include <hurd.h>
+
+/* Create a one-way communication channel (pipe).
+ Actually the channel is two-way on the Hurd.
+ If successful, two file descriptors are stored in FDS;
+ bytes written on FDS[1] can be read from FDS[0].
+ Apply FLAGS to the new file descriptors.
+ Returns 0 if successful, -1 if not. */
+int
+__pipe2 (int fds[2], int flags)
+{
+ int save_errno = errno;
+ int result;
+
+ if (flags & ~(O_CLOEXEC | O_NONBLOCK))
+ return __hurd_fail (EINVAL);
+
+ flags = o_to_sock_flags (flags);
+
+ /* The magic S_IFIFO protocol tells the pflocal server to create
+ sockets which report themselves as FIFOs, as POSIX requires for
+ pipes. */
+ result = __socketpair (PF_LOCAL, SOCK_STREAM | flags, S_IFIFO, fds);
+ if (result == -1 && errno == EPROTONOSUPPORT)
+ {
+ /* We contacted an "old" pflocal server that doesn't support the
+ magic S_IFIFO protocol.
+ FIXME: Remove this junk somewhere in the future. */
+ __set_errno (save_errno);
+ return __socketpair (PF_LOCAL, SOCK_STREAM | flags, 0, fds);
+ }
+
+ return result;
+}
+weak_alias (__pipe2, pipe2)
diff --git a/sysdeps/mach/hurd/profil.c b/sysdeps/mach/hurd/profil.c
index dd77cd3d53..ae79ae6cb8 100644
--- a/sysdeps/mach/hurd/profil.c
+++ b/sysdeps/mach/hurd/profil.c
@@ -68,6 +68,8 @@ update_waiter (u_short *sample_buffer, size_t size, size_t offset, u_int scale)
if (! err)
err = __mach_setup_thread (__mach_task_self (), profile_thread,
&profile_waiter, NULL, NULL);
+ if (! err)
+ err = __mach_setup_tls (profile_thread);
}
else
err = 0;
@@ -100,7 +102,7 @@ update_waiter (u_short *sample_buffer, size_t size, size_t offset, u_int scale)
int
__profile_frequency (void)
{
- return profile_tick;
+ return 1000000 / profile_tick;
}
libc_hidden_def (__profile_frequency)
@@ -137,7 +139,7 @@ __profil (u_short *sample_buffer, size_t size, size_t offset, u_int scale)
weak_alias (__profil, profil)
/* Fetch PC samples. This function must be very careful not to depend
- on Hurd threadvar variables. We arrange that by using a special
+ on Hurd TLS variables. We arrange that by using a special
stub arranged for at the end of this file. */
static void
fetch_samples (void)
@@ -173,7 +175,7 @@ fetch_samples (void)
}
-/* This function must be very careful not to depend on Hurd threadvar
+/* This function must be very careful not to depend on Hurd TLS
variables. We arrange that by using special stubs arranged for at the
end of this file. */
static void
@@ -265,7 +267,7 @@ text_set_element (_hurd_fork_child_hook, fork_profil_child);
are fatal in profile_waiter anyhow. */
#define __mig_put_reply_port(foo)
-/* Use our static variable instead of the usual threadvar mechanism for
+/* Use our static variable instead of the usual TLS mechanism for
this. */
#define __mig_get_reply_port() profil_reply_port
diff --git a/sysdeps/mach/hurd/ptsname.c b/sysdeps/mach/hurd/ptsname.c
index 2978394eb5..73ec57dd70 100644
--- a/sysdeps/mach/hurd/ptsname.c
+++ b/sysdeps/mach/hurd/ptsname.c
@@ -18,6 +18,7 @@
#include <errno.h>
#include <string.h>
+#include <sys/stat.h>
#include <hurd.h>
#include <hurd/fd.h>
#include <hurd/term.h>
@@ -38,11 +39,9 @@ ptsname (int fd)
}
-/* Store at most BUFLEN characters of the pathname of the slave pseudo
- terminal associated with the master FD is open on in BUF.
- Return 0 on success, otherwise an error number. */
+/* We don't need STP, but fill it for conformity with the Linux version... */
int
-__ptsname_r (int fd, char *buf, size_t buflen)
+__ptsname_internal (int fd, char *buf, size_t buflen, struct stat64 *stp)
{
string_t peername;
size_t len;
@@ -58,7 +57,23 @@ __ptsname_r (int fd, char *buf, size_t buflen)
return ERANGE;
}
+ if (stp)
+ {
+ if (__xstat64 (_STAT_VER, peername, stp) < 0)
+ return errno;
+ }
+
memcpy (buf, peername, len);
return 0;
}
+
+
+/* Store at most BUFLEN characters of the pathname of the slave pseudo
+ terminal associated with the master FD is open on in BUF.
+ Return 0 on success, otherwise an error number. */
+int
+__ptsname_r (int fd, char *buf, size_t buflen)
+{
+ return __ptsname_internal (fd, buf, buflen, NULL);
+}
weak_alias (__ptsname_r, ptsname_r)
diff --git a/sysdeps/mach/hurd/reboot.c b/sysdeps/mach/hurd/reboot.c
index 73d2ad7ad4..d3ff94a794 100644
--- a/sysdeps/mach/hurd/reboot.c
+++ b/sysdeps/mach/hurd/reboot.c
@@ -18,6 +18,7 @@
#include <errno.h>
#include <unistd.h>
#include <hurd.h>
+#include <hurd/paths.h>
#include <hurd/startup.h>
#include <sys/reboot.h>
@@ -33,8 +34,8 @@ reboot (int howto)
if (err)
return __hurd_fail (EPERM);
- err = __USEPORT (PROC, __proc_getmsgport (port, 1, &init));
- if (!err)
+ init = __file_name_lookup (_SERVERS_STARTUP, 0, 0);
+ if (init != MACH_PORT_NULL)
{
err = __startup_reboot (init, hostpriv, howto);
__mach_port_deallocate (__mach_task_self (), init);
diff --git a/sysdeps/mach/hurd/recv.c b/sysdeps/mach/hurd/recv.c
index 1534228c0a..d75cf665ba 100644
--- a/sysdeps/mach/hurd/recv.c
+++ b/sysdeps/mach/hurd/recv.c
@@ -37,12 +37,16 @@ __recv (int fd, void *buf, size_t n, int flags)
char *cdata = NULL;
mach_msg_type_number_t clen = 0;
- if (err = HURD_DPORT_USE (fd, __socket_recv (port, &addrport,
+ err = HURD_DPORT_USE (fd, __socket_recv (port, &addrport,
flags, &bufp, &nread,
&ports, &nports,
&cdata, &clen,
&flags,
- n)))
+ n));
+ if (err == MIG_BAD_ID || err == EOPNOTSUPP)
+ /* The file did not grok the socket protocol. */
+ err = ENOTSOCK;
+ if (err)
return __hurd_sockfail (fd, flags, err);
__mach_port_deallocate (__mach_task_self (), addrport);
diff --git a/sysdeps/mach/hurd/recvmsg.c b/sysdeps/mach/hurd/recvmsg.c
index 770a42e05e..2bb6c9ad30 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;
@@ -135,9 +273,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/send.c b/sysdeps/mach/hurd/send.c
index cc7d2a8b86..3bcd749c15 100644
--- a/sysdeps/mach/hurd/send.c
+++ b/sysdeps/mach/hurd/send.c
@@ -33,6 +33,10 @@ __send (int fd, const void *buf, size_t n, int flags)
NULL, MACH_MSG_TYPE_COPY_SEND, 0,
NULL, 0, &wrote));
+ if (err == MIG_BAD_ID || err == EOPNOTSUPP)
+ /* The file did not grok the socket protocol. */
+ err = ENOTSOCK;
+
return err ? __hurd_sockfail (fd, flags, err) : wrote;
}
libc_hidden_def (__send)
diff --git a/sysdeps/mach/hurd/sendmsg.c b/sysdeps/mach/hurd/sendmsg.c
index ce40764992..8367877053 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 (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 (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 9057135222..dc97f86d3c 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 3e16aba175..d6d905e5e6 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 3bd1ac9f0a..5a3202f874 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 23ae4f570e..b0392c49c3 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 170ab26908..2ce928abd4 100644
--- a/sysdeps/mach/hurd/setitimer.c
+++ b/sysdeps/mach/hurd/setitimer.c
@@ -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)
{
@@ -221,11 +225,12 @@ setitimer_locked (const struct itimerval *new, struct itimerval *old,
goto out;
_hurd_itimer_thread_stack_base = 0; /* Anywhere. */
_hurd_itimer_thread_stack_size = __vm_page_size; /* Small stack. */
- if (err = __mach_setup_thread (__mach_task_self (),
+ if ((err = __mach_setup_thread (__mach_task_self (),
_hurd_itimer_thread,
&timer_thread,
&_hurd_itimer_thread_stack_base,
&_hurd_itimer_thread_stack_size))
+ || (err = __mach_setup_tls (_hurd_itimer_thread)))
{
__thread_terminate (_hurd_itimer_thread);
_hurd_itimer_thread = MACH_PORT_NULL;
@@ -348,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
@@ -363,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/setpgid.c b/sysdeps/mach/hurd/setpgid.c
index 8579efb9b1..8c2a29cbab 100644
--- a/sysdeps/mach/hurd/setpgid.c
+++ b/sysdeps/mach/hurd/setpgid.c
@@ -19,6 +19,7 @@
#include <unistd.h>
#include <hurd.h>
#include <hurd/port.h>
+#include <lowlevellock.h>
/* Set the process group ID of the process matching PID to PGID.
If PID is zero, the current process's process group ID is set.
@@ -38,14 +39,7 @@ __setpgid (pid_t pid, pid_t pgid)
/* Synchronize with the signal thread to make sure we have
received and processed proc_newids before returning to the user. */
while (_hurd_pids_changed_stamp == stamp)
- {
-#ifdef noteven
- /* XXX we have no need for a mutex, but cthreads demands one. */
- __condition_wait (&_hurd_pids_changed_sync, NULL);
-#else
- __swtch_pri(0);
-#endif
- }
+ lll_wait (&_hurd_pids_changed_stamp, stamp, 0);
return 0;
diff --git a/sysdeps/mach/hurd/setregid.c b/sysdeps/mach/hurd/setregid.c
index 24797f3968..7e27e31c93 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 256fac4a20..8abda001ec 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 7d33e205ac..8296055430 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 e4e05f6e4c..84f1cf6762 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 c66466686f..746af3cd71 100644
--- a/sysdeps/mach/hurd/setsid.c
+++ b/sysdeps/mach/hurd/setsid.c
@@ -21,6 +21,7 @@
#include <hurd/port.h>
#include <hurd/fd.h>
#include <hurd/ioctl.h>
+#include <lowlevellock.h>
/* Create a new session with the calling process as its leader.
The process group IDs of the session and the calling process
@@ -55,17 +56,11 @@ __setsid (void)
returned by `getpgrp ()' in other threads) has been updated before
we return. */
while (_hurd_pids_changed_stamp == stamp)
- {
-#ifdef noteven
- /* XXX we have no need for a mutex, but cthreads demands one. */
- __condition_wait (&_hurd_pids_changed_sync, NULL);
-#else
- __swtch_pri (0);
-#endif
- }
+ lll_wait (&_hurd_pids_changed_stamp, stamp, 0);
}
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 6fca89c288..c7e92a54c5 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/shmat.c b/sysdeps/mach/hurd/shmat.c
new file mode 100644
index 0000000000..d6e310e66d
--- /dev/null
+++ b/sysdeps/mach/hurd/shmat.c
@@ -0,0 +1,82 @@
+/* SysV shmat for Hurd.
+ Copyright (C) 2005-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 <errno.h>
+#include <utime.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <assert.h>
+#include <sys/mman.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "sysvshm.h"
+
+/* Attach the shared memory segment associated with SHMID to the data
+ segment of the calling process. SHMADDR and SHMFLG determine how
+ and where the segment is attached. */
+void *
+__shmat (int shmid, const void *shmaddr, int shmflg)
+{
+ error_t err;
+ char filename[sizeof (SHM_DIR) - 1 + SHM_NAMEMAX];
+ int fd;
+ void *addr;
+ struct stat statbuf;
+ int res;
+
+ sprintf (filename, SHM_DIR SHM_NAMEPRI, shmid);
+ fd = __open (filename, (shmflg & SHM_RDONLY) ? O_RDONLY : O_RDWR);
+ if (fd < 0)
+ {
+ if (errno == ENOENT)
+ errno = EINVAL;
+ return (void *) -1;
+ }
+
+ res = __fstat (fd, &statbuf);
+ if (res < 0)
+ {
+ err = errno;
+ __close (fd);
+ errno = err;
+ return (void *) -1;
+ }
+
+ addr = __mmap ((void *) shmaddr, statbuf.st_size,
+ PROT_READ | ((shmflg & SHM_RDONLY) ? 0 : PROT_WRITE),
+ MAP_SHARED, fd, 0);
+ __close (fd);
+ if (addr == MAP_FAILED)
+ return (void *) -1;
+
+ err = __sysvshm_add (addr, statbuf.st_size);
+ if (err)
+ {
+ __munmap (addr, statbuf.st_size);
+ errno = err;
+ return (void *) -1;
+ }
+
+ return addr;
+}
+
+weak_alias(__shmat, shmat)
diff --git a/sysdeps/mach/hurd/shmctl.c b/sysdeps/mach/hurd/shmctl.c
new file mode 100644
index 0000000000..a991a0c8de
--- /dev/null
+++ b/sysdeps/mach/hurd/shmctl.c
@@ -0,0 +1,132 @@
+/* SysV shmctl for Hurd.
+ Copyright (C) 2005-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 <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "sysvshm.h"
+
+/* Provide operations to control shared memory segments. */
+int
+__shmctl (int id, int cmd, struct shmid_ds *buf)
+{
+ error_t err = 0;
+ int fd;
+ int res;
+ char filename[sizeof (SHM_DIR) - 1 + SHM_NAMEMAX];
+ struct stat statbuf;
+
+ sprintf (filename, SHM_DIR SHM_NAMEPRI, id);
+ /* SysV requires read access for IPC_STAT. */
+ fd = __open (filename, O_NORW);
+ if (fd < 0)
+ {
+ if (errno == ENOENT)
+ errno = EINVAL;
+ return -1;
+ }
+
+ res = __fstat (fd, &statbuf);
+ if (res < 0)
+ {
+ err = errno;
+ __close (fd);
+ errno = err;
+ return -1;
+ }
+
+ switch (cmd)
+ {
+ case IPC_STAT:
+
+ buf->shm_perm.__key = id;
+ buf->shm_perm.uid = statbuf.st_uid;
+ buf->shm_perm.gid = statbuf.st_gid;
+
+ /* We do not support the creator. */
+ buf->shm_perm.cuid = statbuf.st_uid;
+ buf->shm_perm.cgid = statbuf.st_gid;
+
+ /* We just want the protection bits. */
+ buf->shm_perm.mode = statbuf.st_mode & 0777;
+ /* Hopeless. We do not support a sequence number. */
+ buf->shm_perm.__seq = statbuf.st_ino;
+ buf->shm_segsz = statbuf.st_size;
+
+ /* Hopeless. We do not support any of these. */
+ buf->shm_atime = statbuf.st_atime;
+ buf->shm_dtime = statbuf.st_mtime;
+ /* Well, this comes at least close. */
+ buf->shm_ctime = statbuf.st_ctime;
+
+ /* We do not support the PID. */
+ buf->shm_cpid = 0;
+ buf->shm_lpid = 0;
+
+ if (statbuf.st_mode & S_IMMAP0)
+ buf->shm_nattch = 0;
+ else
+ /* 42 is the answer. Of course this is bogus, but for most
+ applications, this should be fine. */
+ buf->shm_nattch = 42;
+
+ break;
+
+ case IPC_SET:
+ if (statbuf.st_uid != buf->shm_perm.uid
+ || statbuf.st_gid != buf->shm_perm.gid)
+ {
+ res = __fchown (fd,
+ (statbuf.st_uid != buf->shm_perm.uid)
+ ? buf->shm_perm.uid : -1,
+ (statbuf.st_gid != buf->shm_perm.gid)
+ ? buf->shm_perm.gid : -1);
+ if (res < 0)
+ err = errno;
+ }
+
+ if (!err && statbuf.st_mode & 0777 != buf->shm_perm.mode & 0777)
+ {
+ res = __fchmod (fd, (statbuf.st_mode & ~0777)
+ | (buf->shm_perm.mode & 0777));
+ if (res < 0)
+ err = errno;
+ }
+ break;
+
+ case IPC_RMID:
+ res = __unlink (filename);
+ /* FIXME: Check error (mapping ENOENT to EINVAL). */
+ break;
+
+ default:
+ err = EINVAL;
+ }
+
+ __close (fd);
+ errno = err;
+ return err ? -1 : 0;
+}
+
+weak_alias(__shmctl, shmctl)
diff --git a/sysdeps/mach/hurd/shmdt.c b/sysdeps/mach/hurd/shmdt.c
new file mode 100644
index 0000000000..988fab8ee6
--- /dev/null
+++ b/sysdeps/mach/hurd/shmdt.c
@@ -0,0 +1,51 @@
+/* SysV shmdt for Hurd.
+ Copyright (C) 2005-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 <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <assert.h>
+#include <sys/mman.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include "sysvshm.h"
+
+/* Detach shared memory segment starting at address specified by
+ SHMADDR from the caller's data segment. */
+int
+__shmdt (const void *shmaddr)
+{
+ error_t err;
+ size_t size;
+
+ err = __sysvshm_remove ((void *) shmaddr, &size);
+ if (err)
+ {
+ errno = err;
+ return -1;
+ }
+
+ __munmap ((void *) shmaddr, size);
+ return 0;
+}
+
+weak_alias(__shmdt, shmdt)
diff --git a/sysdeps/mach/hurd/shmget.c b/sysdeps/mach/hurd/shmget.c
new file mode 100644
index 0000000000..2065b41989
--- /dev/null
+++ b/sysdeps/mach/hurd/shmget.c
@@ -0,0 +1,242 @@
+/* SysV shmget for Hurd.
+ Copyright (C) 2005-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 <stdbool.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <hurd/fd.h>
+
+#include "sysvshm.h"
+
+/* Create a new shared memory segment file without linking it into the
+ filesystem. Return the directory and file ports in R_DIR and R_FILE. */
+static error_t
+create_shm_file (size_t size, int flags, file_t *r_dir, file_t *r_file)
+{
+ error_t err;
+ file_t dir;
+ file_t file;
+
+ flags &= 0777;
+
+ /* Get a port to the directory that will contain the file. */
+ dir = __file_name_lookup (SHM_DIR, 0, 0);
+ if (dir == MACH_PORT_NULL)
+ return errno;
+
+ /* Create an unnamed file in the directory. */
+ err = __dir_mkfile (dir, O_RDWR, flags, &file);
+ if (err)
+ {
+ __mach_port_deallocate (__mach_task_self (), dir);
+ return err;
+ }
+
+ err = __file_set_size (file, size);
+ if (err)
+ {
+ __mach_port_deallocate (__mach_task_self (), file);
+ __mach_port_deallocate (__mach_task_self (), dir);
+
+ return err;
+ }
+
+ *r_dir = dir;
+ *r_file = file;
+
+ return 0;
+}
+
+
+/* Open the shared memory segment *R_KEY and return a file descriptor
+ to it in R_FD. If KEY is IPC_PRIVATE, use a private key and return
+ it in R_KEY. */
+static error_t
+get_exclusive (int shmflags, size_t size, key_t *r_key, int *r_fd)
+{
+ error_t err;
+ file_t dir;
+ file_t file;
+ char filename[SHM_NAMEMAX];
+ key_t key = *r_key;
+ bool is_private;
+
+ /* Create the shared memory segment. */
+ err = create_shm_file (size, shmflags, &dir, &file);
+ if (err)
+ return err;
+
+ if (key == IPC_PRIVATE)
+ {
+ is_private = true;
+ key = SHM_PRIV_KEY_START;
+
+ /* Try to link the shared memory segment into the filesystem
+ (exclusively). */
+ do
+ {
+ sprintf (filename, SHM_NAMEPRI, key);
+ err = __dir_link (dir, file, filename, 1);
+ if (!err)
+ {
+ /* We are done. */
+ *r_key = key;
+ break;
+ }
+ else if (err == EEXIST)
+ {
+ /* Check if we ran out of keys. If not, try again with new
+ key. */
+ if (key == SHM_PRIV_KEY_END)
+ err = ENOSPC;
+ else
+ err = 0;
+
+ key--;
+ }
+ }
+ while (!err);
+ }
+ else
+ {
+ /* Try to link the shared memory segment into the filesystem
+ (exclusively) under the given key. */
+ sprintf (filename, SHM_NAMEPRI, key);
+ err = __dir_link (dir, file, filename, 1);
+ }
+
+ __mach_port_deallocate (__mach_task_self (), dir);
+
+ if (!err)
+ {
+ int fd;
+
+ /* Get a file descriptor for that port. */
+ fd = _hurd_intern_fd (file, O_RDWR, 1); /* dealloc on error */
+ if (fd < 0)
+ err = errno;
+ else
+ *r_fd = fd;
+ }
+
+ return err;
+}
+
+
+/* Open the shared memory segment KEY (creating it if it doesn't yet
+ exist) and return a file descriptor to it in R_FD. */
+static error_t
+get_shared (int shmflags, size_t size, key_t key, int *r_fd)
+{
+ error_t err = 0;
+ char filename[sizeof (SHM_DIR) - 1 + SHM_NAMEMAX];
+ int fd = -1;
+ sprintf (filename, SHM_DIR SHM_NAMEPRI, key);
+
+ do
+ {
+ fd = __open (filename, O_NORW, shmflags & 0777);
+
+ if (fd < 0 && errno != ENOENT)
+ /* We give up. */
+ return errno;
+ else if (fd >= 0)
+ {
+ int res;
+ struct stat statbuf;
+
+ /* Check the size (we only need to do this if we did not
+ create the shared memory segment file ourselves). */
+ res = __fstat (fd, &statbuf);
+ if (res < 0)
+ {
+ err = errno;
+ __close (fd);
+ return err;
+ }
+
+ if (statbuf.st_size < size)
+ {
+ __close (fd);
+ return EINVAL;
+ }
+ }
+ else
+ {
+ /* The memory segment doesn't exist. */
+ if (shmflags & IPC_CREAT)
+ {
+ /* Try to create it exclusively. */
+ err = get_exclusive (shmflags, size, &key, &fd);
+ if (err == EEXIST)
+ /* If somebody created it in the meanwhile, just try again. */
+ err = 0;
+ }
+ else
+ err = ENOENT;
+ }
+ }
+ while (fd < 0 && !err);
+
+ if (!err)
+ *r_fd = fd;
+ else
+ *r_fd = -1;
+
+ return err;
+}
+
+/* Return an identifier for an shared memory segment of at least size
+ SIZE which is associated with KEY. */
+int
+__shmget (key_t key, size_t size, int shmflags)
+{
+ error_t err;
+ int fd;
+
+ if (key == IPC_PRIVATE || shmflags & IPC_EXCL)
+ /* An exclusive shared memory segment must be created. */
+ err = get_exclusive (shmflags, size, &key, &fd);
+ else
+ err = get_shared (shmflags, size, key, &fd);
+
+ if (err)
+ {
+ errno = err;
+ return -1;
+ }
+
+ /* From here, we can't fail. That's important, as otherwise we
+ would need to unlink the file if we created it (in that case, the
+ code above would have to be changed to pass a "created" flag down
+ to the caller). */
+
+ __close (fd);
+
+ return key;
+}
+
+weak_alias(__shmget, shmget)
diff --git a/sysdeps/mach/hurd/socket.c b/sysdeps/mach/hurd/socket.c
index 34c66a8481..1e1221431e 100644
--- a/sysdeps/mach/hurd/socket.c
+++ b/sysdeps/mach/hurd/socket.c
@@ -21,6 +21,7 @@
#include <hurd/socket.h>
#include <hurd/fd.h>
#include <fcntl.h>
+#include <fcntl-internal.h>
/* Create a new socket of type TYPE in domain DOMAIN, using
protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically.
@@ -30,6 +31,11 @@ __socket (int domain, int type, int protocol)
{
error_t err;
socket_t sock, server;
+ int flags = sock_to_o_flags (type & ~SOCK_TYPE_MASK);
+ type &= SOCK_TYPE_MASK;
+
+ if (flags & ~(O_CLOEXEC | O_NONBLOCK))
+ return __hurd_fail (EINVAL);
/* Find the socket server for DOMAIN. */
server = _hurd_socket_server (domain, 0);
@@ -55,10 +61,17 @@ __socket (int domain, int type, int protocol)
|| err == MIG_BAD_ID || err == EOPNOTSUPP)
err = EAFNOSUPPORT;
+ if (! err)
+ {
+ if (flags & O_NONBLOCK)
+ err = __io_set_some_openmodes (sock, O_NONBLOCK);
+ /* TODO: do we need special ERR massaging after the previous call? */
+ }
+
if (err)
return __hurd_fail (err);
- return _hurd_intern_fd (sock, O_IGNORE_CTTY, 1);
+ return _hurd_intern_fd (sock, O_IGNORE_CTTY | flags, 1);
}
libc_hidden_def (__socket)
diff --git a/sysdeps/mach/hurd/socketpair.c b/sysdeps/mach/hurd/socketpair.c
index 0b0d4e9417..60b6218336 100644
--- a/sysdeps/mach/hurd/socketpair.c
+++ b/sysdeps/mach/hurd/socketpair.c
@@ -17,6 +17,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <fcntl-internal.h>
#include <sys/socket.h>
#include <unistd.h>
@@ -34,6 +35,11 @@ __socketpair (int domain, int type, int protocol, int fds[2])
error_t err;
socket_t server, sock1, sock2;
int d1, d2;
+ int flags = sock_to_o_flags (type & ~SOCK_TYPE_MASK);
+ type &= SOCK_TYPE_MASK;
+
+ if (flags & ~(O_CLOEXEC | O_NONBLOCK))
+ return __hurd_fail (EINVAL);
if (fds == NULL)
return __hurd_fail (EINVAL);
@@ -56,6 +62,14 @@ __socketpair (int domain, int type, int protocol, int fds[2])
return -1;
err = __socket_create (server, type, protocol, &sock1);
}
+ /* TODO: do we need special ERR massaging here, like it is done in
+ __socket? */
+ if (! err)
+ {
+ if (flags & O_NONBLOCK)
+ err = __io_set_some_openmodes (sock1, O_NONBLOCK);
+ /* TODO: do we need special ERR massaging after the previous call? */
+ }
if (err)
return __hurd_fail (err);
if (err = __socket_create (server, type, protocol, &sock2))
@@ -63,7 +77,12 @@ __socketpair (int domain, int type, int protocol, int fds[2])
__mach_port_deallocate (__mach_task_self (), sock1);
return __hurd_fail (err);
}
- if (err = __socket_connect2 (sock1, sock2))
+ if (flags & O_NONBLOCK)
+ err = __io_set_some_openmodes (sock2, O_NONBLOCK);
+ /* TODO: do we need special ERR massaging after the previous call? */
+ if (! err)
+ err = __socket_connect2 (sock1, sock2);
+ if (err)
{
__mach_port_deallocate (__mach_task_self (), sock1);
__mach_port_deallocate (__mach_task_self (), sock2);
@@ -72,13 +91,13 @@ __socketpair (int domain, int type, int protocol, int fds[2])
/* Put the sockets into file descriptors. */
- d1 = _hurd_intern_fd (sock1, O_IGNORE_CTTY, 1);
+ d1 = _hurd_intern_fd (sock1, O_IGNORE_CTTY | flags, 1);
if (d1 < 0)
{
__mach_port_deallocate (__mach_task_self (), sock2);
return -1;
}
- d2 = _hurd_intern_fd (sock2, O_IGNORE_CTTY, 1);
+ d2 = _hurd_intern_fd (sock2, O_IGNORE_CTTY | flags, 1);
if (d2 < 0)
{
err = errno;
diff --git a/sysdeps/mach/hurd/spawni.c b/sysdeps/mach/hurd/spawni.c
index 12fa457c02..1d2dcb2c7b 100644
--- a/sysdeps/mach/hurd/spawni.c
+++ b/sysdeps/mach/hurd/spawni.c
@@ -235,12 +235,11 @@ __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);
_hurd_sigstate_lock (ss);
ints[INIT_SIGMASK] = ss->blocked;
- ints[INIT_SIGPENDING] = _hurd_sigstate_pending (ss); /* XXX really? */
+ 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. */
@@ -366,6 +365,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/mach/hurd/sysdep-cancel.h b/sysdeps/mach/hurd/sysdep-cancel.h
new file mode 100644
index 0000000000..ec55c7330f
--- /dev/null
+++ b/sysdeps/mach/hurd/sysdep-cancel.h
@@ -0,0 +1,9 @@
+#include <sysdep.h>
+
+/* Always multi-thread (since there's at least the sig handler), but no
+ handling enabled. */
+#define SINGLE_THREAD_P (0)
+#define RTLD_SINGLE_THREAD_P (0)
+#define LIBC_CANCEL_ASYNC() 0 /* Just a dummy value. */
+#define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it. */
+#define LIBC_CANCEL_HANDLED() /* Nothing. */
diff --git a/sysdeps/mach/hurd/tls.h b/sysdeps/mach/hurd/tls.h
index 67ed17d00d..6b3189ab5b 100644
--- a/sysdeps/mach/hurd/tls.h
+++ b/sysdeps/mach/hurd/tls.h
@@ -27,6 +27,7 @@
# include <sysdep.h>
# include <mach/mig_errors.h>
# include <mach.h>
+# include <atomic.h>
/* This is the size of the initial TCB. */
@@ -51,6 +52,26 @@
# define GET_DTV(descr) \
(((tcbhead_t *) (descr))->dtv)
+/* Global scope switch support. */
+#define THREAD_GSCOPE_IN_TCB 0
+#define THREAD_GSCOPE_GLOBAL
+#define THREAD_GSCOPE_SET_FLAG() \
+ atomic_exchange_and_add_acq (&GL(dl_thread_gscope_count), 1)
+#define THREAD_GSCOPE_RESET_FLAG() \
+ do \
+ if (atomic_exchange_and_add_rel (&GL(dl_thread_gscope_count), -1) == 1) \
+ lll_wake (&GL(dl_thread_gscope_count), 0); \
+ while (0)
+#define THREAD_GSCOPE_WAIT() \
+ do \
+ { \
+ int count; \
+ atomic_write_barrier (); \
+ while ((count = GL(dl_thread_gscope_count))) \
+ lll_wait (&GL(dl_thread_gscope_count), count, 0); \
+ } \
+ while (0)
+
#endif /* !ASSEMBLER */
diff --git a/sysdeps/mach/hurd/libc-tsd.h b/sysdeps/mach/hurd/truncate64.c
index f523034fe7..a2e2ed2190 100644
--- a/sysdeps/mach/hurd/libc-tsd.h
+++ b/sysdeps/mach/hurd/truncate64.c
@@ -1,5 +1,4 @@
-/* libc-internal interface for thread-specific data. Hurd version.
- Copyright (C) 1998-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2017 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
@@ -16,19 +15,28 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#ifndef _LIBC_TSD_H
-#define _LIBC_TSD_H 1
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <hurd.h>
-#include <hurd/threadvar.h>
+/* Truncate FILE_NAME to LENGTH bytes. */
+int
+__truncate64 (const char *file_name, off64_t length)
+{
+ error_t err;
+ file_t file = __file_name_lookup (file_name, O_WRITE, 0);
-#define __libc_tsd_define(CLASS, TYPE, KEY) /* nothing, always have threadvars */
+ if (file == MACH_PORT_NULL)
+ return -1;
-#define __libc_tsd_address(TYPE, KEY) \
- ((TYPE *) __hurd_threadvar_location (_HURD_THREADVAR_##KEY))
+ err = __file_set_size (file, length);
+ __mach_port_deallocate (__mach_task_self (), file);
-#define __libc_tsd_get(TYPE, KEY) \
- (*__libc_tsd_address (TYPE, KEY))
-#define __libc_tsd_set(TYPE, KEY, VALUE) \
- (*__libc_tsd_address (TYPE, KEY) = (VALUE))
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
-#endif /* libc-tsd.h */
+weak_alias (__truncate64, truncate64)
diff --git a/sysdeps/mach/hurd/utime-helper.c b/sysdeps/mach/hurd/utime-helper.c
new file mode 100644
index 0000000000..357dfe9705
--- /dev/null
+++ b/sysdeps/mach/hurd/utime-helper.c
@@ -0,0 +1,84 @@
+/* Helpers for utimes/utimens conversions.
+ Copyright (C) 2015-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 <errno.h>
+#include <hurd/hurd_types.h>
+#include <stddef.h>
+#include <sys/time.h>
+
+/* Initializes atime/mtime timespec structures from an array of timeval. */
+static inline void
+utime_ts_from_tval (const struct timeval tvp[2],
+ struct timespec *atime, struct timespec *mtime)
+{
+ if (tvp == NULL)
+ {
+ /* Setting the number of nanoseconds to UTIME_NOW tells the
+ underlying filesystems to use the current time. */
+ atime->tv_sec = 0;
+ atime->tv_nsec = UTIME_NOW;
+ mtime->tv_sec = 0;
+ mtime->tv_nsec = UTIME_NOW;
+ }
+ else
+ {
+ TIMEVAL_TO_TIMESPEC (&tvp[0], atime);
+ TIMEVAL_TO_TIMESPEC (&tvp[1], mtime);
+ }
+}
+
+/* Initializes atime/mtime time_value_t structures from an array of timeval. */
+static inline void
+utime_tvalue_from_tval (const struct timeval tvp[2],
+ time_value_t *atime, time_value_t *mtime)
+{
+ if (tvp == NULL)
+ /* Setting the number of microseconds to `-1' tells the
+ underlying filesystems to use the current time. */
+ atime->microseconds = mtime->microseconds = -1;
+ else
+ {
+ atime->seconds = tvp[0].tv_sec;
+ atime->microseconds = tvp[0].tv_usec;
+ mtime->seconds = tvp[1].tv_sec;
+ mtime->microseconds = tvp[1].tv_usec;
+ }
+}
+
+/* Changes the access time of the file behind PORT using a timeval array. */
+static inline error_t
+hurd_futimens (const file_t port, const struct timeval tvp[2])
+{
+ error_t err;
+ struct timespec atime, mtime;
+
+ utime_ts_from_tval (tvp, &atime, &mtime);
+
+ err = __file_utimens (port, atime, mtime);
+
+ if (err == MIG_BAD_ID || err == EOPNOTSUPP)
+ {
+ time_value_t atim, mtim;
+
+ utime_tvalue_from_tval (tvp, &atim, &mtim);
+
+ err = __file_utimes (port, atim, mtim);
+ }
+
+ return err;
+}
diff --git a/sysdeps/mach/hurd/utimes.c b/sysdeps/mach/hurd/utimes.c
index 121b456232..fb6c3f155e 100644
--- a/sysdeps/mach/hurd/utimes.c
+++ b/sysdeps/mach/hurd/utimes.c
@@ -20,33 +20,22 @@
#include <stddef.h>
#include <hurd.h>
+#include "utime-helper.c"
+
/* Change the access time of FILE to TVP[0] and
the modification time of FILE to TVP[1]. */
int
__utimes (const char *file, const struct timeval tvp[2])
{
- union tv
- {
- struct timeval tv;
- time_value_t tvt;
- };
- const union tv *u = (const union tv *) tvp;
- union tv nulltv[2];
error_t err;
file_t port;
- if (tvp == NULL)
- {
- /* Setting the number of microseconds to `-1' tells the
- underlying filesystems to use the current time. */
- nulltv[0].tvt.microseconds = nulltv[1].tvt.microseconds = -1;
- u = nulltv;
- }
-
port = __file_name_lookup (file, 0, 0);
if (port == MACH_PORT_NULL)
return -1;
- err = __file_utimes (port, u[0].tvt, u[1].tvt);
+
+ err = hurd_futimens (port, tvp);
+
__mach_port_deallocate (__mach_task_self (), port);
if (err)
return __hurd_fail (err);
diff --git a/sysdeps/mach/i386/machine-lock.h b/sysdeps/mach/i386/machine-lock.h
index 966f128396..2b5641bb86 100644
--- a/sysdeps/mach/i386/machine-lock.h
+++ b/sysdeps/mach/i386/machine-lock.h
@@ -34,6 +34,9 @@ typedef volatile int __spin_lock_t;
/* Unlock LOCK. */
+extern void __spin_unlock (__spin_lock_t *__lock);
+
+#if defined __USE_EXTERN_INLINES && defined _LIBC
_EXTERN_INLINE void
__spin_unlock (__spin_lock_t *__lock)
{
@@ -42,9 +45,13 @@ __spin_unlock (__spin_lock_t *__lock)
: "=&r" (__unlocked), "=m" (*__lock) : "0" (0)
: "memory");
}
+#endif
/* Try to lock LOCK; return nonzero if we locked it, zero if another has. */
+extern int __spin_try_lock (__spin_lock_t *__lock);
+
+#if defined __USE_EXTERN_INLINES && defined _LIBC
_EXTERN_INLINE int
__spin_try_lock (__spin_lock_t *__lock)
{
@@ -54,14 +61,19 @@ __spin_try_lock (__spin_lock_t *__lock)
: "memory");
return !__locked;
}
+#endif
/* Return nonzero if LOCK is locked. */
+extern int __spin_lock_locked (__spin_lock_t *__lock);
+
+#if defined __USE_EXTERN_INLINES && defined _LIBC
_EXTERN_INLINE int
__spin_lock_locked (__spin_lock_t *__lock)
{
return *__lock != 0;
}
+#endif
#endif /* machine-lock.h */
diff --git a/sysdeps/mach/i386/thread_state.h b/sysdeps/mach/i386/thread_state.h
index abb5ffe8b1..2e081405e3 100644
--- a/sysdeps/mach/i386/thread_state.h
+++ b/sysdeps/mach/i386/thread_state.h
@@ -21,7 +21,8 @@
#include <mach/machine/thread_status.h>
-#define MACHINE_THREAD_STATE_FLAVOR i386_THREAD_STATE
+#define MACHINE_NEW_THREAD_STATE_FLAVOR i386_THREAD_STATE
+#define MACHINE_THREAD_STATE_FLAVOR i386_REGS_SEGS_STATE
#define MACHINE_THREAD_STATE_COUNT i386_THREAD_STATE_COUNT
#define machine_thread_state i386_thread_state
@@ -30,6 +31,14 @@
#define SP uesp
#define SYSRETURN eax
+#define MACHINE_THREAD_STATE_FIX_NEW(ts) do { \
+ asm ("mov %%cs, %w0" : "=q" ((ts)->cs)); \
+ asm ("mov %%ds, %w0" : "=q" ((ts)->ds)); \
+ asm ("mov %%es, %w0" : "=q" ((ts)->es)); \
+ asm ("mov %%fs, %w0" : "=q" ((ts)->fs)); \
+ asm ("mov %%gs, %w0" : "=q" ((ts)->gs)); \
+} while(0)
+
struct machine_thread_all_state
{
int set; /* Mask of bits (1 << FLAVOR). */
diff --git a/sysdeps/mach/libc-lock.h b/sysdeps/mach/libc-lock.h
index 6acc78abd8..3625b2be65 100644
--- a/sysdeps/mach/libc-lock.h
+++ b/sysdeps/mach/libc-lock.h
@@ -20,15 +20,32 @@
#define _LIBC_LOCK_H 1
#ifdef _LIBC
-#include <cthreads.h>
-#define __libc_lock_t struct mutex
+
+#include <tls.h>
+#include <lowlevellock.h>
+
+/* The locking here is very inexpensive, even for inlining. */
+#define _IO_lock_inexpensive 1
+
+typedef unsigned int __libc_lock_t;
+typedef struct
+{
+ __libc_lock_t lock;
+ int cnt;
+ void *owner;
+} __libc_lock_recursive_t;
+
+typedef __libc_lock_recursive_t __rtld_lock_recursive_t;
+
+extern char __libc_lock_self0[0];
+#define __libc_lock_owner_self() \
+ (__LIBC_NO_TLS() ? (void *)&__libc_lock_self0 : THREAD_SELF)
+
#else
typedef struct __libc_lock_opaque__ __libc_lock_t;
+typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
#endif
-/* Type for key of thread specific data. */
-typedef cthread_key_t __libc_key_t;
-
/* Define a lock variable NAME with storage class CLASS. The lock must be
initialized with __libc_lock_init before it can be used (or define it
with __libc_lock_define_initialized, below). Use `extern' for CLASS to
@@ -40,58 +57,141 @@ typedef cthread_key_t __libc_key_t;
CLASS __libc_lock_t NAME;
/* Define an initialized lock variable NAME with storage class CLASS. */
+#define _LIBC_LOCK_INITIALIZER LLL_INITIALIZER
#define __libc_lock_define_initialized(CLASS,NAME) \
- CLASS __libc_lock_t NAME = MUTEX_INITIALIZER;
+ CLASS __libc_lock_t NAME = LLL_INITIALIZER;
/* Initialize the named lock variable, leaving it in a consistent, unlocked
state. */
-#define __libc_lock_init(NAME) __mutex_init (&(NAME))
+#define __libc_lock_init(NAME) (NAME) = LLL_INITIALIZER
/* Finalize the named lock variable, which must be locked. It cannot be
used again until __libc_lock_init is called again on it. This must be
called on a lock variable before the containing storage is reused. */
-#define __libc_lock_fini(NAME) __mutex_unlock (&(NAME))
+#define __libc_lock_fini __libc_lock_unlock
+#define __libc_lock_fini_recursive __libc_lock_unlock_recursive
+#define __rtld_lock_fini_recursive __rtld_lock_unlock_recursive
/* Lock the named lock variable. */
-#define __libc_lock_lock(NAME) __mutex_lock (&(NAME))
+#define __libc_lock_lock(NAME) \
+ ({ lll_lock (&(NAME), 0); 0; })
/* Lock the named lock variable. */
-#define __libc_lock_trylock(NAME) (!__mutex_trylock (&(NAME)))
+#define __libc_lock_trylock(NAME) lll_trylock (&(NAME))
/* Unlock the named lock variable. */
-#define __libc_lock_unlock(NAME) __mutex_unlock (&(NAME))
-
+#define __libc_lock_unlock(NAME) \
+ ({ lll_unlock (&(NAME), 0); 0; })
+
+#define __libc_lock_define_recursive(CLASS,NAME) \
+ CLASS __libc_lock_recursive_t NAME;
+
+#define _LIBC_LOCK_RECURSIVE_INITIALIZER { LLL_INITIALIZER, 0, 0 }
+
+#define __libc_lock_define_initialized_recursive(CLASS,NAME) \
+ CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
+
+#define __rtld_lock_define_recursive(CLASS,NAME) \
+ __libc_lock_define_recursive (CLASS, NAME)
+#define _RTLD_LOCK_RECURSIVE_INITIALIZER \
+ _LIBC_LOCK_RECURSIVE_INITIALIZER
+#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
+ __libc_lock_define_initialized_recursive (CLASS, NAME)
+
+#define __libc_lock_init_recursive(NAME) \
+ ({ \
+ (NAME) = (__libc_lock_recursive_t)_LIBC_LOCK_RECURSIVE_INITIALIZER; \
+ 0; \
+ })
+
+#define __libc_lock_trylock_recursive(NAME) \
+ ({ \
+ __libc_lock_recursive_t *const __lock = &(NAME); \
+ void *__self = __libc_lock_owner_self (); \
+ int __r = 0; \
+ if (__self == __lock->owner) \
+ ++__lock->cnt; \
+ else if ((__r = lll_trylock (&__lock->lock)) == 0) \
+ __lock->owner = __self, __lock->cnt = 1; \
+ __r; \
+ })
+
+#define __libc_lock_lock_recursive(NAME) \
+ ({ \
+ __libc_lock_recursive_t *const __lock = &(NAME); \
+ void *__self = __libc_lock_owner_self (); \
+ if (__self != __lock->owner) \
+ { \
+ lll_lock (&__lock->lock, 0); \
+ __lock->owner = __self; \
+ } \
+ ++__lock->cnt; \
+ (void)0; \
+ })
+
+#define __libc_lock_unlock_recursive(NAME) \
+ ({ \
+ __libc_lock_recursive_t *const __lock = &(NAME); \
+ if (--__lock->cnt == 0) \
+ { \
+ __lock->owner = 0; \
+ lll_unlock (&__lock->lock, 0); \
+ } \
+ })
+
+
+#define __rtld_lock_initialize(NAME) \
+ (void) ((NAME) = (__rtld_lock_recursive_t) _RTLD_LOCK_RECURSIVE_INITIALIZER)
+#define __rtld_lock_trylock_recursive(NAME) \
+ __libc_lock_trylock_recursive (NAME)
+#define __rtld_lock_lock_recursive(NAME) \
+ __libc_lock_lock_recursive(NAME)
+#define __rtld_lock_unlock_recursive(NAME) \
+ __libc_lock_unlock_recursive (NAME)
/* XXX for now */
-#define __libc_rwlock_define __libc_lock_define
-#define __libc_rwlock_define_initialized __libc_lock_define_initialized
-#define __libc_rwlock_init __libc_lock_init
-#define __libc_rwlock_fini __libc_lock_fini
-#define __libc_rwlock_rdlock __libc_lock_lock
-#define __libc_rwlock_wrlock __libc_lock_lock
-#define __libc_rwlock_tryrdlock __libc_lock_trylock
-#define __libc_rwlock_trywrlock __libc_lock_trylock
-#define __libc_rwlock_unlock __libc_lock_unlock
-
+#define __libc_rwlock_define __libc_lock_define_recursive
+#define __libc_rwlock_define_initialized __libc_lock_define_initialized_recursive
+#define __libc_rwlock_init __libc_lock_init_recursive
+#define __libc_rwlock_fini __libc_lock_fini_recursive
+#define __libc_rwlock_rdlock __libc_lock_lock_recursive
+#define __libc_rwlock_wrlock __libc_lock_lock_recursive
+#define __libc_rwlock_tryrdlock __libc_lock_trylock_recursive
+#define __libc_rwlock_trywrlock __libc_lock_trylock_recursive
+#define __libc_rwlock_unlock __libc_lock_unlock_recursive
+
+struct __libc_cleanup_frame
+{
+ void (*__fct) (void *);
+ void *__argp;
+ int __doit;
+};
+
+__extern_inline void
+__libc_cleanup_fct (struct __libc_cleanup_frame *framep)
+{
+ if (framep->__doit)
+ framep->__fct (framep->__argp);
+}
/* Start a critical region with a cleanup function */
-#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
-{ \
- typeof (***(FCT)) *__save_FCT = (DOIT) ? (FCT) : 0; \
- typeof (ARG) __save_ARG = ARG; \
- /* close brace is in __libc_cleanup_region_end below. */
-
-/* End a critical region started with __libc_cleanup_region_start. */
-#define __libc_cleanup_region_end(DOIT) \
- if ((DOIT) && __save_FCT != 0) \
- (*__save_FCT)(__save_ARG); \
-}
+#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
+ do \
+ { \
+ struct __libc_cleanup_frame __cleanup \
+ __attribute__ ((__cleanup__ (__libc_cleanup_fct))) = \
+ { .__fct = (FCT), .__argp = (ARG), .__doit = (DOIT) };
+
+/* This one closes the brace above. */
+#define __libc_cleanup_region_end(DOIT) \
+ __cleanup.__doit = (DOIT); \
+ } \
+ while (0)
-/* Sometimes we have to exit the block in the middle. */
-#define __libc_cleanup_end(DOIT) \
- if ((DOIT) && __save_FCT != 0) \
- (*__save_FCT)(__save_ARG); \
+#define __libc_cleanup_end(DOIT) __cleanup.__doit = (DOIT);
+#define __libc_cleanup_push(fct, arg) __libc_cleanup_region_start (1, fct, arg)
+#define __libc_cleanup_pop(execute) __libc_cleanup_region_end (execute)
/* Use mutexes as once control variables. */
@@ -102,8 +202,7 @@ struct __libc_once
};
#define __libc_once_define(CLASS,NAME) \
- CLASS struct __libc_once NAME = { MUTEX_INITIALIZER, 0 }
-
+ CLASS struct __libc_once NAME = { _LIBC_LOCK_INITIALIZER, 0 }
/* Call handler iff the first call. */
#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
@@ -121,25 +220,11 @@ struct __libc_once
#ifdef _LIBC
/* We need portable names for some functions. E.g., when they are
used as argument to __libc_cleanup_region_start. */
-#define __libc_mutex_unlock __mutex_unlock
-#endif
+#define __libc_mutex_unlock __libc_lock_unlock
-#define __libc_key_create(KEY,DEST) cthread_keycreate (KEY)
-#define __libc_setspecific(KEY,VAL) cthread_setspecific (KEY, VAL)
-void *__libc_getspecific (__libc_key_t key);
-
-/* XXX until cthreads supports recursive locks */
-#define __libc_lock_define_initialized_recursive __libc_lock_define_initialized
-#define __libc_lock_init_recursive __libc_lock_init
-#define __libc_lock_fini_recursive __libc_lock_fini
-#define __libc_lock_trylock_recursive __libc_lock_trylock
-#define __libc_lock_unlock_recursive __libc_lock_unlock
-#define __libc_lock_lock_recursive __libc_lock_lock
-
-#define __rtld_lock_define_initialized_recursive __libc_lock_define_initialized
-#define __rtld_lock_fini_recursive __libc_lock_fini
-#define __rtld_lock_trylock_recursive __libc_lock_trylock
-#define __rtld_lock_unlock_recursive __libc_lock_unlock
-#define __rtld_lock_lock_recursive __libc_lock_lock
+/* Hide the definitions which are only supposed to be used inside libc in
+ a separate file. This file is not present in the installation! */
+# include <libc-lockP.h>
+#endif
#endif /* libc-lock.h */
diff --git a/sysdeps/mach/pagecopy.h b/sysdeps/mach/pagecopy.h
index cda1ef90c6..3bf83ed6f4 100644
--- a/sysdeps/mach/pagecopy.h
+++ b/sysdeps/mach/pagecopy.h
@@ -20,7 +20,10 @@
/* Threshold at which vm_copy is more efficient than well-optimized copying
by words. This parameter should be tuned as necessary. */
-#define PAGE_THRESHOLD (2 * PAGE_SIZE) /* XXX ? */
+#define PAGE_THRESHOLD (16384) /* XXX Tune this. */
+#if 0
+#define PAGE_COPY_THRESHOLD (16384) /* XXX Tune this. */
+#endif
#define PAGE_SIZE __vm_page_size
#define PAGE_COPY_FWD(dstp, srcp, nbytes_left, nbytes) \
diff --git a/sysdeps/mach/thread_state.h b/sysdeps/mach/thread_state.h
index 33f293bf21..c382eb995a 100644
--- a/sysdeps/mach/thread_state.h
+++ b/sysdeps/mach/thread_state.h
@@ -37,6 +37,9 @@
((ts)->SP = (unsigned long int) (stack) + (size))
#endif
#endif
+#ifndef MACHINE_THREAD_STATE_FIX_NEW
+# define MACHINE_THREAD_STATE_FIX_NEW(ts)
+#endif
/* These functions are of use in machine-dependent signal trampoline
implementations. */
diff --git a/sysdeps/microblaze/nptl/tls.h b/sysdeps/microblaze/nptl/tls.h
index 8376f5005e..f8ba021500 100644
--- a/sysdeps/microblaze/nptl/tls.h
+++ b/sysdeps/microblaze/nptl/tls.h
@@ -126,6 +126,7 @@ typedef struct
(descr->member[idx] = (value))
/* Get and set the global scope generation counter in struct pthread. */
+# define THREAD_GSCOPE_IN_TCB 1
# define THREAD_GSCOPE_FLAG_UNUSED 0
# define THREAD_GSCOPE_FLAG_USED 1
# define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/mips/nptl/tls.h b/sysdeps/mips/nptl/tls.h
index 10ca878292..ceabbf0012 100644
--- a/sysdeps/mips/nptl/tls.h
+++ b/sysdeps/mips/nptl/tls.h
@@ -168,6 +168,7 @@ typedef struct
# define NO_TLS_OFFSET -1
/* Get and set the global scope generation counter in struct pthread. */
+#define THREAD_GSCOPE_IN_TCB 1
#define THREAD_GSCOPE_FLAG_UNUSED 0
#define THREAD_GSCOPE_FLAG_USED 1
#define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/nios2/nptl/tls.h b/sysdeps/nios2/nptl/tls.h
index ad29ac5ac2..59442091d3 100644
--- a/sysdeps/nios2/nptl/tls.h
+++ b/sysdeps/nios2/nptl/tls.h
@@ -147,6 +147,7 @@ register struct pthread *__thread_self __asm__("r23");
# define NO_TLS_OFFSET -1
/* Get and set the global scope generation counter in struct pthread. */
+#define THREAD_GSCOPE_IN_TCB 1
#define THREAD_GSCOPE_FLAG_UNUSED 0
#define THREAD_GSCOPE_FLAG_USED 1
#define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/nptl/timer_routines.h b/sysdeps/nptl/timer_routines.h
new file mode 100644
index 0000000000..9931015684
--- /dev/null
+++ b/sysdeps/nptl/timer_routines.h
@@ -0,0 +1,51 @@
+/* Helper code for POSIX timer implementation on NPTL.
+ Copyright (C) 2000-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+ 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; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _TIMER_ROUTINES_H
+#define _TIMER_ROUTINES_H 1
+
+#include <internaltypes.h>
+#include <string.h>
+
+/* Compare two pthread_attr_t thread attributes for exact equality.
+ Returns 1 if they are equal, otherwise zero if they are not equal
+ or contain illegal values. This version is NPTL-specific for
+ performance reason. One could use the access functions to get the
+ values of all the fields of the attribute structure. */
+static inline int
+thread_attr_compare (const pthread_attr_t *left, const pthread_attr_t *right)
+{
+ struct pthread_attr *ileft = (struct pthread_attr *) left;
+ struct pthread_attr *iright = (struct pthread_attr *) right;
+
+ return (ileft->flags == iright->flags
+ && ileft->schedpolicy == iright->schedpolicy
+ && (ileft->schedparam.sched_priority
+ == iright->schedparam.sched_priority)
+ && ileft->guardsize == iright->guardsize
+ && ileft->stackaddr == iright->stackaddr
+ && ileft->stacksize == iright->stacksize
+ && ((ileft->cpuset == NULL && iright->cpuset == NULL)
+ || (ileft->cpuset != NULL && iright->cpuset != NULL
+ && ileft->cpusetsize == iright->cpusetsize
+ && memcmp (ileft->cpuset, iright->cpuset,
+ ileft->cpusetsize) == 0)));
+}
+
+#endif /* timer_routines.h */
diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h
index 0e889bc122..89631003f9 100644
--- a/sysdeps/powerpc/nptl/tls.h
+++ b/sysdeps/powerpc/nptl/tls.h
@@ -246,6 +246,7 @@ register void *__thread_register __asm__ ("r13");
# define NO_TLS_OFFSET -1
/* Get and set the global scope generation counter in struct pthread. */
+#define THREAD_GSCOPE_IN_TCB 1
#define THREAD_GSCOPE_FLAG_UNUSED 0
#define THREAD_GSCOPE_FLAG_USED 1
#define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/pthread/allocalim.h b/sysdeps/pthread/allocalim.h
index 076889463b..1653f9ece2 100644
--- a/sysdeps/pthread/allocalim.h
+++ b/sysdeps/pthread/allocalim.h
@@ -24,6 +24,9 @@ extern __always_inline
int
__libc_use_alloca (size_t size)
{
- return (__builtin_expect (size <= PTHREAD_STACK_MIN / 4, 1)
- || __builtin_expect (__libc_alloca_cutoff (size), 1));
+ return (
+#ifdef PTHREAD_STACK_MIN
+ __builtin_expect (size <= PTHREAD_STACK_MIN / 4, 1) ||
+#endif
+ __builtin_expect (__libc_alloca_cutoff (size), 1));
}
diff --git a/sysdeps/pthread/timer_routines.c b/sysdeps/pthread/timer_routines.c
index 7aa4437a61..3b8c102868 100644
--- a/sysdeps/pthread/timer_routines.c
+++ b/sysdeps/pthread/timer_routines.c
@@ -29,8 +29,11 @@
#include <sys/syscall.h>
#include "posix-timer.h"
-#include <nptl/pthreadP.h>
+#include <timer_routines.h>
+#ifndef DELAYTIMER_MAX
+# define DELAYTIMER_MAX INT_MAX
+#endif
/* Number of threads used. */
#define THREAD_MAXNODES 16
@@ -482,32 +485,6 @@ __timer_thread_wakeup (struct thread_node *thread)
}
-/* Compare two pthread_attr_t thread attributes for exact equality.
- Returns 1 if they are equal, otherwise zero if they are not equal
- or contain illegal values. This version is NPTL-specific for
- performance reason. One could use the access functions to get the
- values of all the fields of the attribute structure. */
-static int
-thread_attr_compare (const pthread_attr_t *left, const pthread_attr_t *right)
-{
- struct pthread_attr *ileft = (struct pthread_attr *) left;
- struct pthread_attr *iright = (struct pthread_attr *) right;
-
- return (ileft->flags == iright->flags
- && ileft->schedpolicy == iright->schedpolicy
- && (ileft->schedparam.sched_priority
- == iright->schedparam.sched_priority)
- && ileft->guardsize == iright->guardsize
- && ileft->stackaddr == iright->stackaddr
- && ileft->stacksize == iright->stacksize
- && ((ileft->cpuset == NULL && iright->cpuset == NULL)
- || (ileft->cpuset != NULL && iright->cpuset != NULL
- && ileft->cpusetsize == iright->cpusetsize
- && memcmp (ileft->cpuset, iright->cpuset,
- ileft->cpusetsize) == 0)));
-}
-
-
/* Search the list of active threads and find one which has matching
attributes. Global mutex lock must be held by caller. */
struct thread_node *
diff --git a/sysdeps/s390/nptl/tls.h b/sysdeps/s390/nptl/tls.h
index e4c3ec7830..4749eb0ffd 100644
--- a/sysdeps/s390/nptl/tls.h
+++ b/sysdeps/s390/nptl/tls.h
@@ -181,6 +181,7 @@ typedef struct
#define THREAD_COPY_POINTER_GUARD(descr)
/* Get and set the global scope generation counter in struct pthread. */
+#define THREAD_GSCOPE_IN_TCB 1
#define THREAD_GSCOPE_FLAG_UNUSED 0
#define THREAD_GSCOPE_FLAG_USED 1
#define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/sh/nptl/tls.h b/sysdeps/sh/nptl/tls.h
index 6f128c9e95..f040496110 100644
--- a/sysdeps/sh/nptl/tls.h
+++ b/sysdeps/sh/nptl/tls.h
@@ -151,6 +151,7 @@ typedef struct
((tcbhead_t *) (descr + 1))->pointer_guard = __tcbp->pointer_guard;})
/* Get and set the global scope generation counter in struct pthread. */
+#define THREAD_GSCOPE_IN_TCB 1
#define THREAD_GSCOPE_FLAG_UNUSED 0
#define THREAD_GSCOPE_FLAG_USED 1
#define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/sparc/nptl/tls.h b/sysdeps/sparc/nptl/tls.h
index 08c055220a..6542c5ff03 100644
--- a/sysdeps/sparc/nptl/tls.h
+++ b/sysdeps/sparc/nptl/tls.h
@@ -151,6 +151,7 @@ register struct pthread *__thread_self __asm__("%g7");
((descr)->header.pointer_guard = THREAD_GET_POINTER_GUARD ())
/* Get and set the global scope generation counter in struct pthread. */
+#define THREAD_GSCOPE_IN_TCB 1
#define THREAD_GSCOPE_FLAG_UNUSED 0
#define THREAD_GSCOPE_FLAG_USED 1
#define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/tile/nptl/tls.h b/sysdeps/tile/nptl/tls.h
index c908fb8e1f..548b30f74b 100644
--- a/sysdeps/tile/nptl/tls.h
+++ b/sysdeps/tile/nptl/tls.h
@@ -172,6 +172,7 @@ register void *__thread_pointer asm ("tp");
# define NO_TLS_OFFSET -1
/* Get and set the global scope generation counter in struct pthread. */
+#define THREAD_GSCOPE_IN_TCB 1
#define THREAD_GSCOPE_FLAG_UNUSED 0
#define THREAD_GSCOPE_FLAG_USED 1
#define THREAD_GSCOPE_FLAG_WAIT 2
diff --git a/sysdeps/unix/bsd/unlockpt.c b/sysdeps/unix/bsd/unlockpt.c
index 436d8a2c0e..0d87086ec0 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 a3fd267e9d..f850fd6eb8 100644
--- a/sysdeps/unix/clock_settime.c
+++ b/sysdeps/unix/clock_settime.c
@@ -21,6 +21,9 @@
#include <libc-internal.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
diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h
index 2b061a07c6..8d19ba0e72 100644
--- a/sysdeps/x86_64/nptl/tls.h
+++ b/sysdeps/x86_64/nptl/tls.h
@@ -366,6 +366,7 @@ typedef struct
/* Get and set the global scope generation counter in the TCB head. */
+# define THREAD_GSCOPE_IN_TCB 1
# define THREAD_GSCOPE_FLAG_UNUSED 0
# define THREAD_GSCOPE_FLAG_USED 1
# define THREAD_GSCOPE_FLAG_WAIT 2