summaryrefslogtreecommitdiff
path: root/hurd
diff options
context:
space:
mode:
Diffstat (limited to 'hurd')
-rw-r--r--hurd/Makefile1
-rw-r--r--hurd/Versions6
-rw-r--r--hurd/hurd/signal.h18
-rw-r--r--hurd/hurd/threadvar.h98
-rw-r--r--hurd/hurdfault.c2
-rw-r--r--hurd/hurdsig.c53
-rw-r--r--hurd/hurdstartup.c1
-rw-r--r--hurd/sigunwind.c4
-rw-r--r--hurd/sysvshm.c97
-rw-r--r--hurd/sysvshm.h52
10 files changed, 207 insertions, 125 deletions
diff --git a/hurd/Makefile b/hurd/Makefile
index 1e7d808ea8..4f35b65a3b 100644
--- a/hurd/Makefile
+++ b/hurd/Makefile
@@ -54,6 +54,7 @@ routines = hurdstartup hurdinit \
vpprintf \
ports-get ports-set hurdports hurdmsg \
errno-loc \
+ sysvshm \
$(sig) $(dtable) $(inlines) port-cleanup report-wait xattr
sig = hurdsig hurdfault siginfo hurd-raise preempt-sig \
trampoline longjmp-ts catch-exc exc2signal hurdkill sigunwind \
diff --git a/hurd/Versions b/hurd/Versions
index d76aabc2da..b84ae791ed 100644
--- a/hurd/Versions
+++ b/hurd/Versions
@@ -4,14 +4,9 @@ libc {
_end;
# variables used in macros & inline functions
- __hurd_sigthread_stack_base; __hurd_sigthread_stack_end;
- __hurd_sigthread_variables;
__hurd_threadvar_max;
__hurd_threadvar_stack_mask; __hurd_threadvar_stack_offset;
- # functions used in macros & inline functions
- __hurd_errno_location;
-
# functions used in libmachuser and libhurduser
_S_catch_exception_raise;
_S_catch_exception_raise_state;
@@ -142,6 +137,7 @@ libc {
HURD_CTHREADS_0.3 {
# weak refs to libthreads functions that libc calls iff libthreads in use
cthread_fork; cthread_detach;
+ pthread_getattr_np; pthread_attr_getstack;
# variables used for detecting cthreads
_cthread_exit_routine; _cthread_init_routine;
diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h
index d8933680cf..c589c59b4e 100644
--- a/hurd/hurd/signal.h
+++ b/hurd/hurd/signal.h
@@ -40,7 +40,6 @@
#include <cthreads.h> /* For `struct mutex'. */
#include <setjmp.h> /* For `jmp_buf'. */
#include <spin-lock.h>
-#include <hurd/threadvar.h> /* We cache sigstate in a threadvar. */
struct hurd_signal_preemptor; /* <hurd/sigpreempt.h> */
@@ -134,8 +133,7 @@ extern struct hurd_sigstate *_hurd_self_sigstate (void)
_HURD_SIGNAL_H_EXTERN_INLINE struct hurd_sigstate *
_hurd_self_sigstate (void)
{
- struct hurd_sigstate **location = (struct hurd_sigstate **)
- (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
+ struct hurd_sigstate **location = &THREAD_SELF->_hurd_sigstate;
if (*location == NULL)
*location = _hurd_thread_sigstate (__mach_thread_self ());
return *location;
@@ -175,9 +173,17 @@ extern void *_hurd_critical_section_lock (void);
_HURD_SIGNAL_H_EXTERN_INLINE void *
_hurd_critical_section_lock (void)
{
- struct hurd_sigstate **location = (struct hurd_sigstate **)
- (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
- struct hurd_sigstate *ss = *location;
+ struct hurd_sigstate **location;
+ struct hurd_sigstate *ss;
+
+#ifdef __LIBC_NO_TLS
+ if (__LIBC_NO_TLS())
+ /* TLS is currently initializing, no need to enter critical section. */
+ return NULL;
+#endif
+
+ location = &THREAD_SELF->_hurd_sigstate;
+ ss = *location;
if (ss == NULL)
{
/* The thread variable is unset; this must be the first time we've
diff --git a/hurd/hurd/threadvar.h b/hurd/hurd/threadvar.h
index 3df8f373f6..ff43598d2c 100644
--- a/hurd/hurd/threadvar.h
+++ b/hurd/hurd/threadvar.h
@@ -20,106 +20,22 @@
#define _HURD_THREADVAR_H
#include <features.h>
+#include <tls.h>
-/* The per-thread variables are found by ANDing this mask
- with the value of the stack pointer and then adding this offset.
-
- In the multi-threaded case, cthreads initialization sets
- __hurd_threadvar_stack_mask to ~(cthread_stack_size - 1), a mask which
- finds the base of the fixed-size cthreads stack; and
- __hurd_threadvar_stack_offset to a small offset that skips the data
- cthreads itself maintains at the base of each thread's stack.
-
- In the single-threaded case, __hurd_threadvar_stack_mask is zero, so the
- stack pointer is ignored; and __hurd_threadvar_stack_offset gives the
- address of a small allocated region which contains the variables for the
- single thread. */
-
-extern unsigned long int __hurd_threadvar_stack_mask;
-extern unsigned long int __hurd_threadvar_stack_offset;
-
-/* A special case must always be made for the signal thread. Even when there
- is only one user thread and an allocated region can be used for the user
- thread's variables, the signal thread needs to have its own location for
- per-thread variables. The variables __hurd_sigthread_stack_base and
+/* The variables __hurd_sigthread_stack_base and
__hurd_sigthread_stack_end define the bounds of the stack used by the
signal thread, so that thread can always be specifically identified. */
extern unsigned long int __hurd_sigthread_stack_base;
extern unsigned long int __hurd_sigthread_stack_end;
-extern unsigned long int *__hurd_sigthread_variables;
-/* At the location described by the two variables above,
- there are __hurd_threadvar_max `unsigned long int's of per-thread data. */
+/* We do not use threadvars any more, this is kept as zero for compatibility with cthreads */
+extern unsigned long int __hurd_threadvar_stack_mask;
+extern unsigned long int __hurd_threadvar_stack_offset;
extern unsigned int __hurd_threadvar_max;
-/* These values are the indices for the standard per-thread variables. */
-enum __hurd_threadvar_index
- {
- _HURD_THREADVAR_MIG_REPLY, /* Reply port for MiG user stub functions. */
- _HURD_THREADVAR_ERRNO, /* `errno' value for this thread. */
- _HURD_THREADVAR_SIGSTATE, /* This thread's `struct hurd_sigstate'. */
- _HURD_THREADVAR_DYNAMIC_USER, /* Dynamically-assigned user variables. */
- _HURD_THREADVAR_MALLOC, /* For use of malloc. */
- _HURD_THREADVAR_DL_ERROR, /* For use of -ldl and dynamic linker. */
- _HURD_THREADVAR_RPC_VARS, /* For state of RPC functions. */
- _HURD_THREADVAR_LOCALE, /* For thread-local locale setting. */
- _HURD_THREADVAR_CTYPE_B, /* Cache of thread-local locale data. */
- _HURD_THREADVAR_CTYPE_TOLOWER, /* Cache of thread-local locale data. */
- _HURD_THREADVAR_CTYPE_TOUPPER, /* Cache of thread-local locale data. */
- _HURD_THREADVAR_MAX /* Default value for __hurd_threadvar_max. */
- };
-
-
-#ifndef _HURD_THREADVAR_H_EXTERN_INLINE
-#define _HURD_THREADVAR_H_EXTERN_INLINE __extern_inline
-#endif
-
-/* Return the location of the value for the per-thread variable with index
- INDEX used by the thread whose stack pointer is SP. */
-
-extern unsigned long int *__hurd_threadvar_location_from_sp
- (enum __hurd_threadvar_index __index, void *__sp);
-
-#if defined __USE_EXTERN_INLINES && defined _LIBC
-# if IS_IN (libc)
-_HURD_THREADVAR_H_EXTERN_INLINE unsigned long int *
-__hurd_threadvar_location_from_sp (enum __hurd_threadvar_index __index,
- void *__sp)
-{
- unsigned long int __stack = (unsigned long int) __sp;
- return &((__stack >= __hurd_sigthread_stack_base &&
- __stack < __hurd_sigthread_stack_end)
- ? __hurd_sigthread_variables
- : (unsigned long int *) ((__stack & __hurd_threadvar_stack_mask) +
- __hurd_threadvar_stack_offset))[__index];
-}
-# endif
-#endif
-
-#include <machine-sp.h> /* Define __thread_stack_pointer. */
-
-/* Return the location of the current thread's value for the
- per-thread variable with index INDEX. */
-
-extern unsigned long int *
-__hurd_threadvar_location (enum __hurd_threadvar_index __index) __THROW
- /* This declaration tells the compiler that the value is constant
- given the same argument. We assume this won't be called twice from
- the same stack frame by different threads. */
- __attribute__ ((__const__));
-
-#if defined __USE_EXTERN_INLINES && defined _LIBC
-# if IS_IN (libc)
-_HURD_THREADVAR_H_EXTERN_INLINE unsigned long int *
-__hurd_threadvar_location (enum __hurd_threadvar_index __index)
-{
- return __hurd_threadvar_location_from_sp (__index,
- __thread_stack_pointer ());
-}
-# endif
-#endif
-
+extern mach_port_t __hurd_reply_port0;
+#define __hurd_local_reply_port (*(__LIBC_NO_TLS() ? &__hurd_reply_port0 : &THREAD_SELF->reply_port))
#endif /* hurd/threadvar.h */
diff --git a/hurd/hurdfault.c b/hurd/hurdfault.c
index 9016227fc9..e3b3927110 100644
--- a/hurd/hurdfault.c
+++ b/hurd/hurdfault.c
@@ -204,6 +204,8 @@ _hurdsig_fault_init (void)
/* This state will be restored when we fault.
It runs the function above. */
memset (&state, 0, sizeof state);
+
+ MACHINE_THREAD_STATE_FIX_NEW (&state);
MACHINE_THREAD_STATE_SET_PC (&state, faulted);
MACHINE_THREAD_STATE_SET_SP (&state, faultstack, sizeof faultstack);
diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c
index fe2eeabfe5..b5c863438d 100644
--- a/hurd/hurdsig.c
+++ b/hurd/hurdsig.c
@@ -20,6 +20,7 @@
#include <string.h>
#include <cthreads.h> /* For `struct mutex'. */
+#include <pthread.h>
#include <mach.h>
#include <mach/thread_switch.h>
@@ -48,7 +49,6 @@ thread_t _hurd_sigthread;
/* These are set up by _hurdsig_init. */
unsigned long int __hurd_sigthread_stack_base;
unsigned long int __hurd_sigthread_stack_end;
-unsigned long int *__hurd_sigthread_variables;
/* Linked-list of per-thread signal state. */
struct hurd_sigstate *_hurd_sigstates;
@@ -234,14 +234,14 @@ abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state,
that this location can be set without faulting, or else return NULL. */
static mach_port_t *
-interrupted_reply_port_location (struct machine_thread_all_state *thread_state,
+interrupted_reply_port_location (thread_t thread,
+ struct machine_thread_all_state *thread_state,
int sigthread)
{
- mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp
- (_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP);
+ mach_port_t *portloc = &THREAD_TCB(thread, thread_state)->reply_port;
if (sigthread && _hurdsig_catch_memory_fault (portloc))
- /* Faulted trying to read the stack. */
+ /* Faulted trying to read the TCB. */
return NULL;
/* Fault now if this pointer is bogus. */
@@ -323,7 +323,8 @@ _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
our nonzero return tells the trampoline code to finish the message
receive operation before running the handler. */
- mach_port_t *reply = interrupted_reply_port_location (state,
+ mach_port_t *reply = interrupted_reply_port_location (ss->thread,
+ state,
sigthread);
error_t err = __interrupt_operation (intr_port, _hurdsig_interrupt_timeout);
@@ -835,7 +836,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
if (! machine_get_basic_state (ss->thread, &thread_state))
goto sigbomb;
- loc = interrupted_reply_port_location (&thread_state, 1);
+ loc = interrupted_reply_port_location (ss->thread,
+ &thread_state, 1);
if (loc && *loc != MACH_PORT_NULL)
/* This is the reply port for the context which called
sigreturn. Since we are abandoning that context entirely
@@ -901,7 +903,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
{
/* Fetch the thread variable for the MiG reply port,
and set it to MACH_PORT_NULL. */
- mach_port_t *loc = interrupted_reply_port_location (&thread_state,
+ mach_port_t *loc = interrupted_reply_port_location (ss->thread,
+ &thread_state,
1);
if (loc)
{
@@ -1255,7 +1258,11 @@ _hurdsig_init (const int *intarray, size_t intarraysize)
/* Start the signal thread listening on the message port. */
- if (__hurd_threadvar_stack_mask == 0)
+#pragma weak cthread_fork
+#pragma weak cthread_detach
+#pragma weak pthread_getattr_np
+#pragma weak pthread_attr_getstack
+ if (!cthread_fork)
{
err = __thread_create (__mach_task_self (), &_hurd_msgport_thread);
assert_perror (err);
@@ -1266,16 +1273,10 @@ _hurdsig_init (const int *intarray, size_t intarraysize)
(vm_address_t *) &__hurd_sigthread_stack_base,
&stacksize);
assert_perror (err);
+ err = __mach_setup_tls (_hurd_msgport_thread);
+ assert_perror (err);
__hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
- __hurd_sigthread_variables =
- malloc (__hurd_threadvar_max * sizeof (unsigned long int));
- if (__hurd_sigthread_variables == NULL)
- __libc_fatal ("hurd: Can't allocate threadvars for signal thread\n");
- memset (__hurd_sigthread_variables, 0,
- __hurd_threadvar_max * sizeof (unsigned long int));
- __hurd_sigthread_variables[_HURD_THREADVAR_LOCALE]
- = (unsigned long int) &_nl_global_locale;
/* Reinitialize the MiG support routines so they will use a per-thread
variable for the cached reply port. */
@@ -1286,6 +1287,7 @@ _hurdsig_init (const int *intarray, size_t intarraysize)
}
else
{
+ cthread_t thread;
/* When cthreads is being used, we need to make the signal thread a
proper cthread. Otherwise it cannot use mutex_lock et al, which
will be the cthreads versions. Various of the message port RPC
@@ -1295,9 +1297,20 @@ _hurdsig_init (const int *intarray, size_t intarraysize)
we'll let the signal thread's per-thread variables be found as for
any normal cthread, and just leave the magic __hurd_sigthread_*
values all zero so they'll be ignored. */
-#pragma weak cthread_fork
-#pragma weak cthread_detach
- cthread_detach (cthread_fork ((cthread_fn_t) &_hurd_msgport_receive, 0));
+ cthread_detach (thread = cthread_fork ((cthread_fn_t) &_hurd_msgport_receive, 0));
+
+ if (pthread_getattr_np)
+ {
+ /* Record stack layout for fork() */
+ pthread_attr_t attr;
+ void *addr;
+ size_t size;
+
+ pthread_getattr_np ((pthread_t) thread, &attr);
+ pthread_attr_getstack (&attr, &addr, &size);
+ __hurd_sigthread_stack_base = (uintptr_t) addr;
+ __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + size;
+ }
/* XXX We need the thread port for the signal thread further on
in this thread (see hurdfault.c:_hurdsigfault_init).
diff --git a/hurd/hurdstartup.c b/hurd/hurdstartup.c
index 9de8f2a898..edfd96fcbd 100644
--- a/hurd/hurdstartup.c
+++ b/hurd/hurdstartup.c
@@ -23,7 +23,6 @@
#include <hurd.h>
#include <hurd/exec_startup.h>
#include <sysdep.h>
-#include <hurd/threadvar.h>
#include <unistd.h>
#include <elf.h>
#include <set-hooks.h>
diff --git a/hurd/sigunwind.c b/hurd/sigunwind.c
index 1f224621bb..a999173c50 100644
--- a/hurd/sigunwind.c
+++ b/hurd/sigunwind.c
@@ -18,6 +18,7 @@
#include <hurd.h>
#include <thread_state.h>
+#include <hurd/threadvar.h>
#include <jmpbuf-unwind.h>
#include <assert.h>
#include <stdint.h>
@@ -38,8 +39,7 @@ _hurdsig_longjmp_from_handler (void *data, jmp_buf env, int val)
{
/* Destroy the MiG reply port used by the signal handler, and restore
the reply port in use by the thread when interrupted. */
- mach_port_t *reply_port =
- (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY);
+ mach_port_t *reply_port = &__hurd_local_reply_port;
if (*reply_port)
{
mach_port_t port = *reply_port;
diff --git a/hurd/sysvshm.c b/hurd/sysvshm.c
new file mode 100644
index 0000000000..5d538a6373
--- /dev/null
+++ b/hurd/sysvshm.c
@@ -0,0 +1,97 @@
+/* SysV shared memory 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 <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/shm.h>
+
+
+/* Description of an shm attachment. */
+struct sysvshm_attach
+{
+ /* Linked list. */
+ struct sysvshm_attach *next;
+
+ /* Map address. */
+ void *addr;
+
+ /* Map size. */
+ size_t size;
+};
+
+/* List of attachments. */
+static struct sysvshm_attach *sysvshm_list;
+
+/* A lock to protect the linked list of shared memory attachments. */
+static struct mutex sysvshm_lock = MUTEX_INITIALIZER;
+
+
+/* Adds a segment attachment. */
+error_t
+__sysvshm_add (void *addr, size_t size)
+{
+ struct sysvshm_attach *shm;
+
+ shm = malloc (sizeof (*shm));
+ if (shm == NULL)
+ return errno;
+
+ __mutex_lock (&sysvshm_lock);
+ shm->addr = addr;
+ shm->size = size;
+ shm->next = sysvshm_list;
+ sysvshm_list = shm;
+ __mutex_unlock (&sysvshm_lock);
+
+ return 0;
+}
+
+/* Removes a segment attachment. On success, returns 0 and sets *SIZE to its
+ size. Returns EINVAL if not found. */
+error_t
+__sysvshm_remove (void *addr, size_t *size)
+{
+ struct sysvshm_attach *shm;
+ struct sysvshm_attach **pshm = &sysvshm_list;
+
+ __mutex_lock (&sysvshm_lock);
+ shm = sysvshm_list;
+ while (shm != NULL)
+ {
+ shm = *pshm;
+ if (shm->addr == addr)
+ {
+ *pshm = shm->next;
+ *size = shm->size;
+ __mutex_unlock (&sysvshm_lock);
+ free (shm);
+ return 0;
+ }
+ pshm = &shm->next;
+ shm = shm->next;
+ }
+ __mutex_unlock (&sysvshm_lock);
+ return EINVAL;
+}
diff --git a/hurd/sysvshm.h b/hurd/sysvshm.h
new file mode 100644
index 0000000000..8b9c29ff46
--- /dev/null
+++ b/hurd/sysvshm.h
@@ -0,0 +1,52 @@
+/* SysV shared memory 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/>. */
+
+#ifndef _HURD_SYSVSHM_H
+#define _HURD_SYSVSHM_H
+
+#include <paths.h>
+#include <hurd.h>
+
+/* The area (from top to bottom) that is used for private keys. These
+ are all keys that have the second highest bit set. */
+#define SHM_PRIV_KEY_START INT_MAX
+#define SHM_PRIV_KEY_END ((INT_MAX / 2) + 1)
+
+#define SHM_PREFIX "sysvshm-"
+#define SHM_DIR _PATH_DEV "shm/"
+
+/* The maximum number of characters in a shared memory segment file name.
+ 32 is the max number of characters in a 128 bit number in hex. */
+#if __WORDSIZE > 128
+#error Need to increase SHM_NAMEMAX.
+#else
+#define SHM_NAMEMAX (sizeof (SHM_PREFIX) - 1 + 32 + 1)
+#endif
+
+/* Use this with printf and its variants. */
+#define SHM_NAMEPRI SHM_PREFIX "%0x"
+
+
+/* Adds a segment attachment. */
+error_t __sysvshm_add (void *addr, size_t size);
+
+/* Removes a segment attachment. On success, returns 0 and sets *SIZE to its
+ size. Returns EINVAL if not found. */
+error_t __sysvshm_remove (void *addr, size_t *size);
+
+#endif /* sysvshm.h */