[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

altered pthread implementation for GNU/kFreeBSD



Hi,

Please would you consider including Petr's patch in experimental
uploads so that it can be more widely tested?

Thanks!

2011/9/20 Petr Salinger <Petr.Salinger@seznam.cz>:
> Hi,
>
> as you might know, our eglibc pthread implementation
> is still linuxthreads based. I tried to alter current
> LT version to use some thread primitives from kernel.
>
> Instead of processes it uses kernel threads,
> there is still a thread manager.
> But it should fix #639658.
>
> The hackish patch is attached, the geting/seting
> of pthread scheduler priority have to be reimplemented.
>
> There is no regression in our glibc testsuite on ka.
> But it definitely needs more testing, on both real HW
> and inside emulators.
>
> Please test this partial patch, upload into experimental would be nice.
>
> Petr

-- 
Robert Millan
diff -u a/linuxthreads/attr.c b/linuxthreads/attr.c
--- a/linuxthreads/attr.c	2006-08-17 03:23:45.000000000 +0200
+++ b/linuxthreads/attr.c	2011-09-20 17:02:25.000000000 +0200
@@ -365,11 +365,11 @@
 			 ? PTHREAD_CREATE_DETACHED
 			 : PTHREAD_CREATE_JOINABLE);
 
-  attr->__schedpolicy = __sched_getscheduler (descr->p_pid);
+  attr->__schedpolicy = __sched_getscheduler (getpid());
   if (attr->__schedpolicy == -1)
     return errno;
 
-  if (__sched_getparam (descr->p_pid,
+  if (__sched_getparam (getpid(),
 			(struct sched_param *) &attr->__schedparam) != 0)
     return errno;
 
diff -u a/linuxthreads/cancel.c b/linuxthreads/cancel.c
--- a/linuxthreads/cancel.c	2006-08-17 03:23:45.000000000 +0200
+++ b/linuxthreads/cancel.c	2011-09-20 17:02:25.000000000 +0200
@@ -89,7 +89,7 @@
 int pthread_cancel(pthread_t thread)
 {
   pthread_handle handle = thread_handle(thread);
-  int pid;
+  long ktid;
   int dorestart = 0;
   pthread_descr th;
   pthread_extricate_if *pextricate;
@@ -112,7 +112,7 @@
   }
 
   pextricate = th->p_extricate;
-  pid = th->p_pid;
+  ktid = th->p_ktid;
 
   /* If the thread has registered an extrication interface, then
      invoke the interface. If it returns 1, then we succeeded in
@@ -139,7 +139,7 @@
   if (dorestart)
     restart(th);
   else
-    kill(pid, __pthread_sig_cancel);
+    __thr_kill(ktid, __pthread_sig_cancel);
 
   return 0;
 }
diff -u a/linuxthreads/descr.h b/linuxthreads/descr.h
--- a/linuxthreads/descr.h	2011-09-20 19:38:20.000000000 +0200
+++ b/linuxthreads/descr.h	2011-09-20 17:44:58.000000000 +0200
@@ -26,6 +26,42 @@
 #include <lowlevellock.h>
 #include <tls.h>
 
+
+extern long int syscall (long int __sysno, ...);
+#include <sys/syscall.h>
+// should be in <sys/thr.h> 
+struct rtprio;
+struct thr_param {
+    void        (*start_func)(void *);  /* thread entry function. */
+    void        *arg;                   /* argument for entry function. */
+    char        *stack_base;            /* stack base address. */
+    size_t      stack_size;             /* stack size. */
+    char        *tls_base;              /* tls base address. */
+    size_t      tls_size;               /* tls size. */
+    long        *child_tid;             /* address to store new TID. */
+    long        *parent_tid;            /* parent accesses the new TID here. */
+    int         flags;                  /* thread flags. */
+    struct rtprio       *rtp;           /* Real-time scheduling priority */
+    void        *spare[3];              /* TODO: cpu affinity mask etc. */
+};
+
+#define KTID_TERMINATED  1
+static inline int __thr_self(long *ktid)
+{ return syscall(SYS_thr_self, ktid);};
+  
+static inline int __thr_kill(long ktid, int signo)
+{ return syscall(SYS_thr_kill, ktid, signo);};  
+
+static inline int __thr_exit(long *ktid)	// also *ktid = KTID_TERMINATED, wakeup(ktid)
+{ return syscall(SYS_thr_exit, ktid);}; 	// returns only for last thread in process
+
+static inline int __thr_new(struct thr_param *param, int param_size)
+{ return syscall(SYS_thr_new, param, param_size);};
+
+static inline int __lll_wait(long *addr, long val)
+{ return syscall(SYS__umtx_op, addr, UMTX_OP_WAIT, val, NULL, NULL);};
+
+
 /* Fast thread-specific data internal to libc.  */
 enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
 			_LIBC_TSD_KEY_DL_ERROR,
@@ -202,6 +238,8 @@
   size_t p_alloca_cutoff;	/* Maximum size which should be allocated
 				   using alloca() instead of malloc().  */
   /* New elements must be added at the end.  */
+  long p_ktid;                  /* kernel thread ID */
+
 
   /* This member must be last.  */
   char end_padding[];
diff -u a/linuxthreads/join.c b/linuxthreads/join.c
--- a/linuxthreads/join.c	2006-08-17 03:23:45.000000000 +0200
+++ b/linuxthreads/join.c	2011-09-20 17:02:25.000000000 +0200
@@ -89,6 +89,9 @@
   }
   /* Threads other than the main one  terminate without flushing stdio streams
      or running atexit functions. */
+     
+  __thr_kill(__manager_thread->p_ktid, __pthread_sig_cancel);
+  __thr_exit(&(self->p_ktid));
   _exit(0);
 }
 
diff -u a/linuxthreads/manager.c b/linuxthreads/manager.c
--- a/linuxthreads/manager.c	2006-08-17 03:23:45.000000000 +0200
+++ b/linuxthreads/manager.c	2011-09-20 19:04:23.000000000 +0200
@@ -151,13 +151,16 @@
   while(1) {
     n = __poll(&ufd, 1, 2000);
 
+#if 0
+    /* iff the main thread terminated abnormally, the signal should kill all threads already */
     /* Check for termination of the main thread */
     if (getppid() == 1) {
       pthread_kill_all_threads(SIGKILL, 0);
       _exit(0);
     }
+#endif    
     /* Check for dead children */
-    if (terminated_children) {
+    if (terminated_children || main_thread_exiting) {
       terminated_children = 0;
       pthread_reap_children();
     }
@@ -182,7 +185,7 @@
                                 request.req_args.create.fn,
                                 request.req_args.create.arg,
                                 &request.req_args.create.mask,
-                                request.req_thread->p_pid,
+                                request.req_thread->p_ktid,
 				request.req_thread->p_report_events,
 				&request.req_thread->p_eventbuf.eventmask);
         restart(request.req_thread);
@@ -271,10 +274,13 @@
 #endif
   /* Make sure our pid field is initialized, just in case we get there
      before our father has initialized it. */
-  THREAD_SETMEM(self, p_pid, __getpid());
+  // done in  kernel   
+  // __thr_self(&ktid);   
+  // THREAD_SETMEM(self, p_ktid, ktid);
   /* Initial signal mask is that of the creating thread. (Otherwise,
      we'd just inherit the mask of the thread manager.) */
   sigprocmask(SIG_SETMASK, &self->p_start_args.mask, NULL);
+#if 0  
   /* Set the scheduling policy and priority for the new thread, if needed */
   if (THREAD_GETMEM(self, p_start_args.schedpolicy) >= 0)
     /* Explicit scheduling attributes were provided: apply them */
@@ -290,6 +296,7 @@
       __sched_setscheduler(THREAD_GETMEM(self, p_pid),
                            SCHED_OTHER, &default_params);
     }
+#endif    
 #if !(USE_TLS && HAVE___THREAD)
   /* Initialize thread-locale current locale to point to the global one.
      With __thread support, the variable's initializer takes care of this.  */
@@ -324,7 +331,9 @@
 #endif
   /* Make sure our pid field is initialized, just in case we get there
      before our father has initialized it. */
-  THREAD_SETMEM(self, p_pid, __getpid());
+  // done in kernel   
+  // __thr_self(&ktid);   
+  // THREAD_SETMEM(self, p_ktid, ktid);
   /* Get the lock the manager will free once all is correctly set up.  */
   __pthread_lock (THREAD_GETMEM(self, p_lock), NULL);
   /* Free it immediately.  */
@@ -586,7 +595,7 @@
 				 td_thr_events_t *event_maskp)
 {
   size_t sseg;
-  int pid;
+  int rv;
   pthread_descr new_thread;
   char *stack_addr;
   char * new_thread_bottom;
@@ -595,6 +604,7 @@
   size_t guardsize = 0, stksize = 0;
   int pagesize = __getpagesize();
   int saved_errno = 0;
+  struct thr_param p;
 
 #ifdef USE_TLS
   new_thread = _dl_allocate_tls (NULL);
@@ -690,6 +700,7 @@
     new_thread->p_detached = attr->__detachstate;
     new_thread->p_userstack = attr->__stackaddr_set;
 
+#if 0
     switch(attr->__inheritsched) {
     case PTHREAD_EXPLICIT_SCHED:
       new_thread->p_start_args.schedpolicy = attr->__schedpolicy;
@@ -702,6 +713,7 @@
       __sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
       break;
     }
+#endif    
     new_thread->p_priority =
       new_thread->p_start_args.schedparam.sched_priority;
   }
@@ -717,7 +729,7 @@
   __pthread_manager_adjust_prio(new_thread->p_priority);
   /* Do the cloning.  We have to use two different functions depending
      on whether we are debugging or not.  */
-  pid = 0;	/* Note that the thread never can have PID zero.  */
+  rv = 0;
   if (report_events)
     {
       /* See whether the TD_CREATE event bit is set in any of the
@@ -733,30 +745,22 @@
 
 	  /* We have to report this event.  */
 #ifdef NEED_SEPARATE_REGISTER_STACK
-	  /* Perhaps this version should be used on all platforms. But
-	   this requires that __clone2 be uniformly supported
-	   everywhere.
-
-	   And there is some argument for changing the __clone2
-	   interface to pass sp and bsp instead, making it more IA64
-	   specific, but allowing stacks to grow outward from each
-	   other, to get less paging and fewer mmaps.  */
-	  pid = __clone2(pthread_start_thread_event,
-  		 (void **)new_thread_bottom,
-			 (char *)stack_addr - new_thread_bottom,
-			 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
-			 __pthread_sig_cancel, new_thread);
+#error unimplemented SEPARATE_REGISTER_STACK
 #elif _STACK_GROWS_UP
-	  pid = __clone(pthread_start_thread_event, (void *) new_thread_bottom,
-			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
-			__pthread_sig_cancel, new_thread);
+#error unimplemented _STACK_GROWS_UP
 #else
-	  pid = __clone(pthread_start_thread_event, stack_addr,
-			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
-			__pthread_sig_cancel, new_thread);
+      memset(&p, 0, sizeof(p));
+      p.start_func = pthread_start_thread_event;
+      p.arg        = new_thread;
+      p.stack_base = new_thread_bottom;
+      p.stack_size = stack_addr - new_thread_bottom;
+      p.tls_base   = new_thread;
+      p.child_tid  = &(new_thread->p_ktid);
+   
+      rv = __thr_new(&p, sizeof(p));
 #endif
 	  saved_errno = errno;
-	  if (pid != -1)
+	  if (rv != -1)
 	    {
 	      /* Now fill in the information about the new thread in
 		 the newly created thread's data structure.  We cannot let
@@ -769,7 +773,7 @@
 	      /* We have to set the PID here since the callback function
 		 in the debug library will need it and we cannot guarantee
 		 the child got scheduled before the debugger.  */
-	      new_thread->p_pid = pid;
+               // kernel already done that
 
 	      /* Now call the function which signals the event.  */
 	      __linuxthreads_create_event ();
@@ -779,27 +783,31 @@
 	    }
 	}
     }
-  if (pid == 0)
+
+  if (rv == 0)
     {
 #ifdef NEED_SEPARATE_REGISTER_STACK
-      pid = __clone2(pthread_start_thread,
-		     (void **)new_thread_bottom,
-                     (char *)stack_addr - new_thread_bottom,
-		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
-		     __pthread_sig_cancel, new_thread);
+#error unimplemented SEPARATE_REGISTER_STACK
 #elif _STACK_GROWS_UP
-      pid = __clone(pthread_start_thread, (void *) new_thread_bottom,
-		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
-		    __pthread_sig_cancel, new_thread);
+#error unimplemented _STACK_GROWS_UP
 #else
-      pid = __clone(pthread_start_thread, stack_addr,
-		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
-		    __pthread_sig_cancel, new_thread);
+
+      memset(&p, 0, sizeof(p));
+      p.start_func = pthread_start_thread;
+      p.arg        = new_thread;
+      p.stack_base = new_thread_bottom;
+      p.stack_size = stack_addr - new_thread_bottom;
+      p.tls_base   = new_thread;
+      p.child_tid  = &(new_thread->p_ktid);
+   
+      rv = __thr_new(&p, sizeof(p));
+
 #endif /* !NEED_SEPARATE_REGISTER_STACK */
       saved_errno = errno;
     }
+
   /* Check if cloning succeeded */
-  if (pid == -1) {
+  if (rv == -1) {
     /* Free the stack if we allocated it */
     if (attr == NULL || !attr->__stackaddr_set)
       {
@@ -843,7 +851,7 @@
   __pthread_main_thread->p_nextlive = new_thread;
   /* Set pid field of the new thread, in case we get there before the
      child starts. */
-  new_thread->p_pid = pid;
+  // kernel already done that
   return 0;
 }
 
@@ -928,17 +936,18 @@
 
 /* Handle threads that have exited */
 
-static void pthread_exited(pid_t pid)
+static void pthread_reap_children(void)
 {
-  pthread_descr th;
+  pthread_descr th, tth;
   int detached;
+  
   /* Find thread with that pid */
   for (th = __pthread_main_thread->p_nextlive;
        th != __pthread_main_thread;
        th = th->p_nextlive) {
-    if (th->p_pid == pid) {
+    if (th->p_ktid == KTID_TERMINATED) {
       /* Remove thread from list of active threads */
-      th->p_nextlive->p_prevlive = th->p_prevlive;
+      tth = th->p_nextlive->p_prevlive = th->p_prevlive;
       th->p_prevlive->p_nextlive = th->p_nextlive;
       /* Mark thread as exited, and if detached, free its resources */
       __pthread_lock(th->p_lock, NULL);
@@ -966,7 +975,7 @@
       __pthread_unlock(th->p_lock);
       if (detached)
 	pthread_free(th);
-      break;
+      th = tth;	
     }
   }
   /* If all threads have exited and the main thread is pending on a
@@ -978,22 +987,6 @@
   }
 }
 
-static void pthread_reap_children(void)
-{
-  pid_t pid;
-  int status;
-
-  while ((pid = waitpid_not_cancel(-1, &status, WNOHANG | __WCLONE)) > 0) {
-    pthread_exited(pid);
-    if (WIFSIGNALED(status)) {
-      /* If a thread died due to a signal, send the same signal to
-         all other threads, including the main thread. */
-      pthread_kill_all_threads(WTERMSIG(status), 1);
-      _exit(0);
-    }
-  }
-}
-
 /* Try to free the resources of a thread when requested by pthread_join
    or pthread_detach on a terminated thread. */
 
@@ -1030,10 +1023,10 @@
   for (th = __pthread_main_thread->p_nextlive;
        th != __pthread_main_thread;
        th = th->p_nextlive) {
-    kill(th->p_pid, sig);
+    __thr_kill(th->p_ktid, sig);
   }
   if (main_thread_also) {
-    kill(__pthread_main_thread->p_pid, sig);
+    __thr_kill(__pthread_main_thread->p_ktid, sig);
   }
 }
 
@@ -1071,18 +1064,24 @@
   for (th = issuing_thread->p_nextlive;
        th != issuing_thread;
        th = th->p_nextlive) {
-    kill(th->p_pid, __pthread_sig_cancel);
+    __thr_kill(th->p_ktid, __pthread_sig_cancel);
   }
   /* Now, wait for all these threads, so that they don't become zombies
      and their times are properly added to the thread manager's times. */
   for (th = issuing_thread->p_nextlive;
        th != issuing_thread;
        th = th->p_nextlive) {
-    waitpid(th->p_pid, NULL, __WCLONE);
+    if (th == __pthread_main_thread)	// it waits for thread manager
+        continue;
+    long ktid;
+    while (KTID_TERMINATED != (ktid = th->p_ktid))
+        __lll_wait(&(th->p_ktid), ktid);
   }
   __fresetlockfiles();
   restart(issuing_thread);
-  _exit(0);
+  __thr_exit(&(manager_thread->p_ktid));
+  // should not return */
+  _exit(__pthread_exit_code);
 }
 
 /* Handler for __pthread_sig_cancel in thread manager thread */
@@ -1114,11 +1113,12 @@
 void __pthread_manager_adjust_prio(int thread_prio)
 {
   struct sched_param param;
-
+#if 0
   if (thread_prio <= manager_thread->p_priority) return;
   param.sched_priority =
     thread_prio < __sched_get_priority_max(SCHED_FIFO)
     ? thread_prio + 1 : thread_prio;
   __sched_setscheduler(manager_thread->p_pid, SCHED_FIFO, &param);
   manager_thread->p_priority = thread_prio;
+#endif  
 }
diff -u a/linuxthreads/pthread.c b/linuxthreads/pthread.c
--- a/linuxthreads/pthread.c	2011-09-20 19:38:19.000000000 +0200
+++ b/linuxthreads/pthread.c	2011-09-20 17:28:00.000000000 +0200
@@ -520,6 +522,7 @@
 {
   struct sigaction sa;
   sigset_t mask;
+  long ktid;
 
   /* If already done (e.g. by a constructor called earlier!), bail out */
   if (__pthread_initial_thread_bos != NULL) return;
@@ -548,14 +551,16 @@
 #endif
 #ifdef USE_TLS
   /* Update the descriptor for the initial thread. */
-  THREAD_SETMEM (((pthread_descr) NULL), p_pid, __getpid());
+  __thr_self(&ktid);
+  THREAD_SETMEM (((pthread_descr) NULL), p_ktid, ktid);
 # ifndef HAVE___THREAD
   /* Likewise for the resolver state _res.  */
   THREAD_SETMEM (((pthread_descr) NULL), p_resp, &_res);
 # endif
 #else
   /* Update the descriptor for the initial thread. */
-  __pthread_initial_thread.p_pid = __getpid();
+  __thr_self(&ktid);
+  __pthread_initial_thread.p_ktid = ktid;
   /* Likewise for the resolver state _res.  */
   __pthread_initial_thread.p_resp = &_res;
 #endif
@@ -629,7 +634,8 @@
 int __pthread_initialize_manager(void)
 {
   int manager_pipe[2];
-  int pid;
+  int rv;
+  struct thr_param p;
   struct pthread_request request;
   int report_events;
   pthread_descr mgr;
@@ -743,7 +749,7 @@
   __pthread_manager_reader = manager_pipe[0]; /* reading end */
 
   /* Start the thread manager */
-  pid = 0;
+  rv = 0;
 #ifdef USE_TLS
   if (__linuxthreads_initial_report_events != 0)
     THREAD_SETMEM (((pthread_descr) NULL), p_report_events,
@@ -776,24 +782,22 @@
 	  __pthread_lock(mgr->p_lock, NULL);
 
 #ifdef NEED_SEPARATE_REGISTER_STACK
-	  pid = __clone2(__pthread_manager_event,
-			 (void **) __pthread_manager_thread_bos,
-			 THREAD_MANAGER_STACK_SIZE,
-			 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM,
-			 mgr);
+#error unimplemented SEPARATE_REGISTER_STACK
 #elif _STACK_GROWS_UP
-	  pid = __clone(__pthread_manager_event,
-			(void **) __pthread_manager_thread_bos,
-			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM,
-			mgr);
+#error unimplemented  STACK_GROWS_UP
 #else
-	  pid = __clone(__pthread_manager_event,
-			(void **) __pthread_manager_thread_tos,
-			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM,
-			mgr);
+      memset(&p, 0, sizeof(p));
+      p.start_func = __pthread_manager_event;
+      p.arg        = mgr;
+      p.stack_base = __pthread_manager_thread_bos;
+      p.stack_size = __pthread_manager_thread_tos - __pthread_manager_thread_bos;
+      p.tls_base   = mgr;
+      p.child_tid  = &(mgr->p_ktid);
+   
+      rv = __thr_new(&p, sizeof(p));
 #endif
 
-	  if (pid != -1)
+	  if (rv != -1)
 	    {
 	      /* Now fill in the information about the new thread in
 	         the newly created thread's data structure.  We cannot let
@@ -803,7 +807,6 @@
 	      mgr->p_eventbuf.eventnum = TD_CREATE;
 	      __pthread_last_event = mgr;
 	      mgr->p_tid = 2* PTHREAD_THREADS_MAX + 1;
-	      mgr->p_pid = pid;
 
 	      /* Now call the function which signals the event.  */
 	      __linuxthreads_create_event ();
@@ -814,21 +817,26 @@
 	}
     }
 
-  if (__builtin_expect (pid, 0) == 0)
+  if (__builtin_expect (rv, 0) == 0)
     {
+
 #ifdef NEED_SEPARATE_REGISTER_STACK
-      pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos,
-		     THREAD_MANAGER_STACK_SIZE,
-		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr);
+#error unimplemented SEPARATE_REGISTER_STACK
 #elif _STACK_GROWS_UP
-      pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos,
-		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr);
+#error unimplemented  STACK_GROWS_UP
 #else
-      pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
-		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr);
+      memset(&p, 0, sizeof(p));
+      p.start_func = __pthread_manager;
+      p.arg        = mgr;
+      p.stack_base = __pthread_manager_thread_bos;
+      p.stack_size = __pthread_manager_thread_tos - __pthread_manager_thread_bos;
+      p.tls_base   = mgr;
+      p.child_tid  = &(mgr->p_ktid);
+   
+      rv = __thr_new(&p, sizeof(p));
 #endif
     }
-  if (__builtin_expect (pid, 0) == -1) {
+  if (__builtin_expect (rv, 0) == -1) {
 #ifdef USE_TLS
     _dl_deallocate_tls (tcbp, true);
 #endif
@@ -838,7 +846,6 @@
     return -1;
   }
   mgr->p_tid = 2* PTHREAD_THREADS_MAX + 1;
-  mgr->p_pid = pid;
   /* Make gdb aware of new thread manager */
   if (__builtin_expect (__pthread_threads_debug, 0) && __pthread_sig_debug > 0)
     {
@@ -998,7 +1005,7 @@
     return ESRCH;
   }
   th = handle->h_descr;
-  if (__builtin_expect (__sched_setscheduler(th->p_pid, policy, param) == -1,
+  if (__builtin_expect (__sched_setscheduler(getpid(), policy, param) == -1,
 			0)) {
     __pthread_unlock(&handle->h_lock);
     return errno;
@@ -1022,7 +1029,7 @@
     __pthread_unlock(&handle->h_lock);
     return ESRCH;
   }
-  pid = handle->h_descr->p_pid;
+  pid = getpid();
   __pthread_unlock(&handle->h_lock);
   pol = __sched_getscheduler(pid);
   if (__builtin_expect (pol, 0) == -1) return errno;
@@ -1062,9 +1069,11 @@
     if (self == __pthread_main_thread)
       {
 #ifdef USE_TLS
-	waitpid(manager_thread->p_pid, NULL, __WCLONE);
+        long ktid;
+        while (KTID_TERMINATED != (ktid = manager_thread->p_ktid))
+            __lll_wait(&(manager_thread->p_ktid), ktid);
 #else
-	waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
+#error TLS required
 #endif
 	/* Since all threads have been asynchronously terminated
            (possibly holding locks), free cannot be used any more.
@@ -1128,9 +1137,11 @@
        children, so that timings for main thread account for all threads. */
     if (self == __pthread_main_thread) {
 #ifdef USE_TLS
-      waitpid(manager_thread->p_pid, NULL, __WCLONE);
+        long ktid;
+        while (KTID_TERMINATED != (ktid = manager_thread->p_ktid))
+            __lll_wait(&(manager_thread->p_ktid), ktid);
 #else
-      waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
+#error TLS required
 #endif
     }
     _exit(__pthread_exit_code);
@@ -1170,6 +1181,7 @@
 
 void __pthread_reset_main_thread(void)
 {
+  long ktid;
   pthread_descr self = thread_self();
 
   if (__pthread_manager_request != -1) {
@@ -1183,7 +1195,8 @@
   }
 
   /* Update the pid of the main thread */
-  THREAD_SETMEM(self, p_pid, __getpid());
+  __thr_self(&ktid);
+  THREAD_SETMEM(self, p_ktid, ktid);
   /* Make the forked thread the main thread */
   __pthread_main_thread = self;
   THREAD_SETMEM(self, p_nextlive, self);
@@ -1289,7 +1302,7 @@
 void __pthread_restart_old(pthread_descr th)
 {
   if (pthread_atomic_increment(&th->p_resume_count) == -1)
-    kill(th->p_pid, __pthread_sig_restart);
+    __thr_kill(th->p_ktid, __pthread_sig_restart);
 }
 
 void __pthread_suspend_old(pthread_descr self)
@@ -1383,7 +1396,7 @@
      memory so the woken thread will have a consistent view.  Complementary
      read barriers are present to the suspend functions. */
   WRITE_MEMORY_BARRIER();
-  kill(th->p_pid, __pthread_sig_restart);
+  __thr_kill(th->p_ktid, __pthread_sig_restart);
 }
 
 /* There is no __pthread_suspend_new because it would just
diff -u a/linuxthreads/signals.c b/linuxthreads/signals.c
--- a/linuxthreads/signals.c	2011-09-20 19:38:19.000000000 +0200
+++ b/linuxthreads/signals.c	2011-09-20 17:02:25.000000000 +0200
@@ -57,16 +57,16 @@
 int pthread_kill(pthread_t thread, int signo)
 {
   pthread_handle handle = thread_handle(thread);
-  int pid;
+  long  ktid;
 
   __pthread_lock(&handle->h_lock, NULL);
   if (invalid_handle(handle, thread)) {
     __pthread_unlock(&handle->h_lock);
     return ESRCH;
   }
-  pid = handle->h_descr->p_pid;
+  ktid = handle->h_descr->p_ktid;
   __pthread_unlock(&handle->h_lock);
-  if (kill(pid, signo) == -1)
+  if (__thr_kill(ktid, signo) == -1)
     return errno;
   else
     return 0;

Reply to: