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