tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
pthread threadreg
hi,
is there anyone working on PTHREAD__HAVE_THREADREG stuffs?
i have a patch for i386, which is enough to make wine work. (attached)
i'm not sure if it can be done in this way for other ports.
esp. for ones without _UC_MACHINE_PAD.
(if ucontext_t had some spare members...)
YAMAMOTO Takashi
Index: sys/sys/ucontext.h
===================================================================
RCS file: /cvsroot/src/sys/sys/ucontext.h,v
retrieving revision 1.11
diff -u -p -r1.11 ucontext.h
--- sys/sys/ucontext.h 15 Oct 2008 06:51:21 -0000 1.11
+++ sys/sys/ucontext.h 24 Sep 2009 04:12:29 -0000
@@ -57,6 +57,7 @@ struct __ucontext {
#define _UC_STACK 0x02 /* valid uc_stack */
#define _UC_CPU 0x04 /* valid GPR context in
uc_mcontext */
#define _UC_FPU 0x08 /* valid FPU context in
uc_mcontext */
+#define _UC_LWPPRIVATE 0x10 /* valid lwp private in uc_mcontext */
#ifdef _KERNEL
struct lwp;
Index: sys/arch/i386/i386/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.671
diff -u -p -r1.671 machdep.c
--- sys/arch/i386/i386/machdep.c 18 Aug 2009 16:41:02 -0000 1.671
+++ sys/arch/i386/i386/machdep.c 24 Sep 2009 04:12:30 -0000
@@ -1833,6 +1833,14 @@ cpu_setmcontext(struct lwp *l, const mco
tf->tf_esp = gr[_REG_UESP];
tf->tf_ss = gr[_REG_SS];
}
+ if ((flags & _UC_LWPPRIVATE) != 0) {
+ /*
+ * abuse _REG_ESP for the private pointer.
+ * cf. _lwp_makecontext
+ */
+ l->l_private = (void *)gr[_REG_ESP];
+ cpu_lwp_setprivate(l, l->l_private);
+ }
#if NNPX > 0
/*
Index: lib/libc/arch/i386/gen/_lwp.c
===================================================================
RCS file: /cvsroot/src/lib/libc/arch/i386/gen/_lwp.c,v
retrieving revision 1.6
diff -u -p -r1.6 _lwp.c
--- lib/libc/arch/i386/gen/_lwp.c 28 Apr 2008 20:22:56 -0000 1.6
+++ lib/libc/arch/i386/gen/_lwp.c 24 Sep 2009 04:12:30 -0000
@@ -66,5 +66,11 @@ _lwp_makecontext(ucontext_t *u, void (*s
/* LINTED uintptr_t is safe */
u->uc_mcontext.__gregs[_REG_UESP] = (uintptr_t) sp;
- /* LINTED private is currently unused */
+ /*
+ * abuse _REG_ESP to pass the private pointer.
+ * cf. cpu_setmcontext
+ */
+ /* LINTED uintptr_t is safe */
+ u->uc_mcontext.__gregs[_REG_ESP] = (uintptr_t)private;
+ u->uc_flags |= _UC_LWPPRIVATE;
}
Index: lib/libpthread/Makefile
===================================================================
RCS file: /cvsroot/src/lib/libpthread/Makefile,v
retrieving revision 1.56
diff -u -p -r1.56 Makefile
--- lib/libpthread/Makefile 16 May 2009 22:21:18 -0000 1.56
+++ lib/libpthread/Makefile 24 Sep 2009 04:12:31 -0000
@@ -86,6 +86,7 @@ pthread_mutex.po: pthread_mutex.o
cp pthread_mutex.o pthread_mutex.po
COPTS.pthread.c += -Wno-stack-protector
+COPTS.pthread.c += -Wno-extra
MAN+= affinity.3 pthread.3 \
pthread_attr.3 \
Index: lib/libpthread/pthread.c
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread.c,v
retrieving revision 1.112
diff -u -p -r1.112 pthread.c
--- lib/libpthread/pthread.c 2 Jul 2009 09:59:00 -0000 1.112
+++ lib/libpthread/pthread.c 24 Sep 2009 04:12:31 -0000
@@ -65,8 +65,10 @@ RB_PROTOTYPE_STATIC(__pthread__alltree,
static void pthread__create_tramp(void *);
static void pthread__initthread(pthread_t);
static void pthread__scrubthread(pthread_t, char *, int);
+#if !defined(PTHREAD__HAVE_THREADREG)
static int pthread__stackid_setup(void *, size_t, pthread_t *);
static int pthread__stackalloc(pthread_t *);
+#endif /* !defined(PTHREAD__HAVE_THREADREG) */
static void pthread__initmain(pthread_t *);
static void pthread__fork_callback(void);
static void pthread__reap(pthread_t);
@@ -377,6 +379,14 @@ pthread_create(pthread_t *thread, const
* and initialize it.
*/
if (newthread == NULL) {
+#if defined(PTHREAD__HAVE_THREADREG)
+ newthread = malloc(sizeof(*newthread));
+ if (newthread == NULL) {
+ free(name);
+ return ENOMEM;
+ }
+ newthread->pt_userstack = true;
+#else /* defined(PTHREAD__HAVE_THREADREG) */
ret = pthread__stackalloc(&newthread);
if (ret != 0) {
if (name)
@@ -391,6 +401,7 @@ pthread_create(pthread_t *thread, const
#endif
newthread->pt_uc.uc_stack = newthread->pt_stack;
newthread->pt_uc.uc_link = NULL;
+#endif /* defined(PTHREAD__HAVE_THREADREG) */
/* Add to list of all threads. */
pthread_rwlock_wrlock(&pthread__alltree_lock);
@@ -402,6 +413,51 @@ pthread_create(pthread_t *thread, const
pthread__initthread(newthread);
}
+#if defined(PTHREAD__HAVE_THREADREG)
+ if (p != NULL && p->ptap_stackaddr != NULL) {
+ if (!newthread->pt_userstack) {
+ const size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
+
+#if defined(__MACHINE_STACK_GROWS_UP)
+ munmap((char *)newthread->pt_stack.ss_sp,
+ newthread->pt_stack.ss_size + pagesize);
+#else /* defined(__MACHINE_STACK_GROWS_UP) */
+ munmap((char *)newthread->pt_stack.ss_sp - pagesize,
+ newthread->pt_stack.ss_size + pagesize);
+#endif /* defined(__MACHINE_STACK_GROWS_UP) */
+ }
+ newthread->pt_userstack = true;
+ newthread->pt_stack.ss_size = p->ptap_stacksize;
+ newthread->pt_stack.ss_sp = p->ptap_stackaddr;
+ } else if (newthread->pt_userstack) {
+ const size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
+ char *base;
+
+ base = mmap(NULL, pthread__stacksize, PROT_READ|PROT_WRITE,
+ MAP_ANON|MAP_PRIVATE, -1, 0);
+ if (base == MAP_FAILED) {
+ free(name);
+ return ENOMEM;
+ }
+ newthread->pt_userstack = false;
+ newthread->pt_stack.ss_size = pthread__stacksize - pagesize;
+#if defined(__MACHINE_STACK_GROWS_UP)
+ mprotect(base + pthread__stacksize - pagesize, pagesize,
+ PROT_NONE);
+ newthread->pt_stack.ss_sp = base;
+#else /* defined(__MACHINE_STACK_GROWS_UP) */
+ mprotect(base, pagesize, PROT_NONE);
+ newthread->pt_stack.ss_sp = base + pagesize;
+#endif /* defined(__MACHINE_STACK_GROWS_UP) */
+ }
+ _INITCONTEXT_U(&newthread->pt_uc);
+#ifdef PTHREAD_MACHINE_HAS_ID_REGISTER
+ pthread__uc_id(&newthread->pt_uc) = newthread;
+#endif
+ newthread->pt_uc.uc_stack = newthread->pt_stack;
+ newthread->pt_uc.uc_link = NULL;
+#endif /* defined(PTHREAD__HAVE_THREADREG) */
+
/*
* Create the new LWP.
*/
@@ -1159,6 +1215,7 @@ pthread__unpark_all(pthread_queue_t *que
#undef OOPS
+#if !defined(PTHREAD__HAVE_THREADREG)
/*
* Allocate a stack for a thread, and set it up. It needs to be aligned, so
* that a thread can find itself by its stack pointer.
@@ -1179,7 +1236,7 @@ pthread__stackalloc(pthread_t *newt)
return pthread__stackid_setup(addr, pthread__stacksize, newt);
}
-
+#endif /* !defined(PTHREAD__HAVE_THREADREG) */
/*
* Set up the slightly special stack for the "initial" thread, which
@@ -1194,7 +1251,10 @@ pthread__initmain(pthread_t *newt)
pthread_t t;
void *base;
size_t size;
- int error, ret;
+#if !defined(PTHREAD__HAVE_THREADREG)
+ int error;
+#endif /* !defined(PTHREAD__HAVE_THREADREG) */
+ int ret;
char *value;
pagesize = (size_t)sysconf(_SC_PAGESIZE);
@@ -1228,18 +1288,30 @@ pthread__initmain(pthread_t *newt)
base = (void *)(pthread__sp() & pthread__threadmask);
size = pthread__stacksize;
+#if defined(PTHREAD__HAVE_THREADREG)
+ t = base;
+ t->pt_stack.ss_size = size - pagesize * 2;
+#if defined(__MACHINE_STACK_GROWS_UP)
+ t->pt_stack.ss_sp = (char *)base + pagesize;
+#else /* defined(__MACHINE_STACK_GROWS_UP) */
+ mprotect((char *)base + pagesize, pagesize, PROT_NONE);
+ t->pt_stack.ss_sp = (char *)base + pagesize * 2;
+#endif /* defined(__MACHINE_STACK_GROWS_UP) */
+#else /* defined(PTHREAD__HAVE_THREADREG) */
error = pthread__stackid_setup(base, size, &t);
if (error) {
/* XXX */
errx(2, "failed to setup main thread: error=%d", error);
}
-
+#endif /* defined(PTHREAD__HAVE_THREADREG) */
+ t->pt_userstack = true;
*newt = t;
/* Set up identity register. */
(void)_lwp_setprivate(t);
}
+#if !defined(PTHREAD__HAVE_THREADREG)
static int
/*ARGSUSED*/
pthread__stackid_setup(void *base, size_t size, pthread_t *tp)
@@ -1272,6 +1344,7 @@ pthread__stackid_setup(void *base, size_
*tp = t;
return 0;
}
+#endif /* !defined(PTHREAD__HAVE_THREADREG) */
#ifndef lint
static int
Index: lib/libpthread/pthread_attr.c
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread_attr.c,v
retrieving revision 1.12
diff -u -p -r1.12 pthread_attr.c
--- lib/libpthread/pthread_attr.c 18 Jan 2009 12:14:16 -0000 1.12
+++ lib/libpthread/pthread_attr.c 24 Sep 2009 04:12:31 -0000
@@ -385,6 +385,7 @@ pthread_attr_getstackaddr(const pthread_
int
pthread_attr_setstackaddr(pthread_attr_t *attr, void *addr)
{
+#if defined(PTHREAD__HAVE_THREADREG)
struct pthread_attr_private *p;
p = pthread__attr_init_private(attr);
@@ -394,6 +395,9 @@ pthread_attr_setstackaddr(pthread_attr_t
p->ptap_stackaddr = addr;
return 0;
+#else /* defined(PTHREAD__HAVE_THREADREG) */
+ return ENOTSUP;
+#endif /* defined(PTHREAD__HAVE_THREADREG) */
}
Index: lib/libpthread/pthread_int.h
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread_int.h,v
retrieving revision 1.72
diff -u -p -r1.72 pthread_int.h
--- lib/libpthread/pthread_int.h 17 May 2009 14:49:00 -0000 1.72
+++ lib/libpthread/pthread_int.h 24 Sep 2009 04:12:31 -0000
@@ -52,6 +52,7 @@
#include <lwp.h>
#include <signal.h>
+#include <stdbool.h>
#ifdef __GNUC__
#define PTHREAD_HIDE __attribute__ ((visibility("hidden")))
@@ -108,6 +109,8 @@ struct __pthread_st {
pthread_cond_t pt_joiners; /* Threads waiting to join. */
void *(*pt_func)(void *);/* Function to call at start. */
void *pt_arg; /* Argumen to pass at start. */
+ bool pt_userstack; /* user-supplied stack
+ (pthread_attr_setstack) */
/* Threads to defer waking, usually until pthread_mutex_unlock(). */
lwpid_t pt_waiters[PTHREAD__UNPARK_MAX];
@@ -253,7 +256,9 @@ int pthread__find(pthread_t) PTHREAD_HID
#define pthread__id(sp) \
((pthread_t) (((vaddr_t)(sp)) & pthread__threadmask))
-#ifdef PTHREAD__HAVE_THREADREG
+#if defined(PTHREAD__HAVE_MD_PTHREAD_SELF)
+#define pthread__self() pthread__md_self()
+#elif defined(PTHREAD__HAVE_THREADREG)
#define pthread__self() pthread__threadreg_get()
#else
#define pthread__self() (pthread__id(pthread__sp()))
Index: lib/libpthread/arch/i386/pthread_md.h
===================================================================
RCS file: /cvsroot/src/lib/libpthread/arch/i386/pthread_md.h,v
retrieving revision 1.17
diff -u -p -r1.17 pthread_md.h
--- lib/libpthread/arch/i386/pthread_md.h 16 May 2009 22:20:40 -0000
1.17
+++ lib/libpthread/arch/i386/pthread_md.h 24 Sep 2009 04:12:31 -0000
@@ -46,6 +46,16 @@ pthread__sp(void)
#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_UESP])
+static inline pthread_t
+pthread__md_self(void)
+{
+ void *ret;
+
+ /* 0 == offsetof(pthread_t, pt_self) */
+ __asm("movl %%gs:0, %0" : "=r" (ret));
+ return ret;
+}
+
/*
* Set initial, sane values for registers whose values aren't just
* "don't care".
@@ -75,11 +85,13 @@ pthread__sp(void)
} while (/*CONSTCOND*/0);
#define pthread__smt_pause() __asm __volatile("rep; nop" :::
"memory")
-/* #define PTHREAD__HAVE_THREADREG */
/* Don't need additional memory barriers. */
#define PTHREAD__ATOMIC_IS_MEMBAR
+#define PTHREAD__HAVE_THREADREG
+#define PTHREAD__HAVE_MD_PTHREAD_SELF
+
static inline pthread_t
#ifdef __GNUC__
__attribute__ ((__const__))
Home |
Main Index |
Thread Index |
Old Index