svn commit: [25637] branches/uClibc-nptl/libpthread/linuxthreads: sysdeps/i386

vda at uclibc.org vda at uclibc.org
Thu Mar 12 20:56:23 UTC 2009


Author: vda
Date: 2009-03-12 20:56:23 +0000 (Thu, 12 Mar 2009)
New Revision: 25637

Log:
linuxthreads fixes from Will Newton (will.newton AT gmail.com):
* share Sys V semaphores in order to get appropriate SEM_UNDO semantics.
* correct guardaddr in pthread_free() for TLS case
* move spinlock unlocking before restart()
* When exit was called from a signal handler, the restart
  from the manager processing the exit request instead restarted the thread
  in pthread_cond_timedwait.
  (see http://sources.redhat.com/ml/libc-ports/2006-05/msg00000.html)



Modified:
   branches/uClibc-nptl/libpthread/linuxthreads/descr.h
   branches/uClibc-nptl/libpthread/linuxthreads/manager.c
   branches/uClibc-nptl/libpthread/linuxthreads/pthread.c
   branches/uClibc-nptl/libpthread/linuxthreads/specific.c
   branches/uClibc-nptl/libpthread/linuxthreads/spinlock.c
   branches/uClibc-nptl/libpthread/linuxthreads/spinlock.h
   branches/uClibc-nptl/libpthread/linuxthreads/sysdeps/i386/tls.h


Changeset:
Modified: branches/uClibc-nptl/libpthread/linuxthreads/descr.h
===================================================================
--- branches/uClibc-nptl/libpthread/linuxthreads/descr.h	2009-03-12 20:29:24 UTC (rev 25636)
+++ branches/uClibc-nptl/libpthread/linuxthreads/descr.h	2009-03-12 20:56:23 UTC (rev 25637)
@@ -123,9 +123,7 @@
       union dtv *dtvp;
       pthread_descr self;	/* Pointer to this structure */
       int multiple_threads;
-# ifdef NEED_DL_SYSINFO
       uintptr_t sysinfo;
-# endif
     } data;
     void *__padding[16];
   } p_header;

Modified: branches/uClibc-nptl/libpthread/linuxthreads/manager.c
===================================================================
--- branches/uClibc-nptl/libpthread/linuxthreads/manager.c	2009-03-12 20:29:24 UTC (rev 25636)
+++ branches/uClibc-nptl/libpthread/linuxthreads/manager.c	2009-03-12 20:56:23 UTC (rev 25637)
@@ -742,15 +742,15 @@
 	  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_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
 			 __pthread_sig_cancel, new_thread);
 #elif _STACK_GROWS_UP
 	  pid = __clone(pthread_start_thread_event, (void *) new_thread_bottom,
-			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
 			__pthread_sig_cancel, new_thread);
 #else
 	  pid = __clone(pthread_start_thread_event, stack_addr,
-			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
 			__pthread_sig_cancel, new_thread);
 #endif
 	  saved_errno = errno;
@@ -783,15 +783,15 @@
       pid = __clone2(pthread_start_thread,
 		     (void **)new_thread_bottom,
                      (char *)stack_addr - new_thread_bottom,
-		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
 		     __pthread_sig_cancel, new_thread);
 #elif _STACK_GROWS_UP
       pid = __clone(pthread_start_thread, (void *) new_thread_bottom,
-		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
 		    __pthread_sig_cancel, new_thread);
 #else
       pid = __clone(pthread_start_thread, stack_addr,
-		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
 		    __pthread_sig_cancel, new_thread);
 #endif /* !NEED_SEPARATE_REGISTER_STACK */
       saved_errno = errno;
@@ -892,10 +892,11 @@
 #ifdef _STACK_GROWS_UP
 # ifdef USE_TLS
       size_t stacksize = guardaddr - th->p_stackaddr;
+      guardaddr = th->p_stackaddr;
 # else
       size_t stacksize = guardaddr - (char *)th;
+      guardaddr = (char *)th;
 # endif
-      guardaddr = (char *)th;
 #else
       /* Guardaddr is always set, even if guardsize is 0.  This allows
 	 us to compute everything else.  */

Modified: branches/uClibc-nptl/libpthread/linuxthreads/pthread.c
===================================================================
--- branches/uClibc-nptl/libpthread/linuxthreads/pthread.c	2009-03-12 20:29:24 UTC (rev 25636)
+++ branches/uClibc-nptl/libpthread/linuxthreads/pthread.c	2009-03-12 20:56:23 UTC (rev 25637)
@@ -740,17 +740,17 @@
 	  pid = __clone2(__pthread_manager_event,
 			 (void **) __pthread_manager_thread_bos,
 			 THREAD_MANAGER_STACK_SIZE,
-			 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+			 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM,
 			 mgr);
 #elif _STACK_GROWS_UP
 	  pid = __clone(__pthread_manager_event,
 			(void **) __pthread_manager_thread_bos,
-			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM,
 			mgr);
 #else
 	  pid = __clone(__pthread_manager_event,
 			(void **) __pthread_manager_thread_tos,
-			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM,
 			mgr);
 #endif
 
@@ -780,13 +780,13 @@
 #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, mgr);
+		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr);
 #elif _STACK_GROWS_UP
       pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos,
-		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, mgr);
+		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr);
 #else
       pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
-		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, mgr);
+		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr);
 #endif
     }
   if (__builtin_expect (pid, 0) == -1) {
@@ -972,6 +972,10 @@
     struct pthread_request request;
     pthread_descr self = thread_self();
 
+    /* Make sure we come back here after suspend(), in case we entered
+       from a signal handler.  */
+    THREAD_SETMEM(self, p_signal_jmp, NULL);
+
     request.req_thread = self;
     request.req_kind = REQ_PROCESS_EXIT;
     request.req_args.exit.code = retcode;
@@ -1201,13 +1205,13 @@
 
 void __pthread_restart_old(pthread_descr th)
 {
-  if (atomic_increment(&th->p_resume_count) == -1)
+  if (pthread_atomic_increment(&th->p_resume_count) == -1)
     kill(th->p_pid, __pthread_sig_restart);
 }
 
 void __pthread_suspend_old(pthread_descr self)
 {
-  if (atomic_decrement(&self->p_resume_count) <= 0)
+  if (pthread_atomic_decrement(&self->p_resume_count) <= 0)
     __pthread_wait_for_restart_signal(self);
 }
 
@@ -1218,7 +1222,7 @@
   int was_signalled = 0;
   sigjmp_buf jmpbuf;
 
-  if (atomic_decrement(&self->p_resume_count) == 0) {
+  if (pthread_atomic_decrement(&self->p_resume_count) == 0) {
     /* Set up a longjmp handler for the restart signal, unblock
        the signal and sleep. */
 
@@ -1275,9 +1279,9 @@
      being delivered. */
 
   if (!was_signalled) {
-    if (atomic_increment(&self->p_resume_count) != -1) {
+    if (pthread_atomic_increment(&self->p_resume_count) != -1) {
       __pthread_wait_for_restart_signal(self);
-      atomic_decrement(&self->p_resume_count); /* should be zero now! */
+      pthread_atomic_decrement(&self->p_resume_count); /* should be zero now! */
       /* woke spontaneously and consumed restart signal */
       return 1;
     }

Modified: branches/uClibc-nptl/libpthread/linuxthreads/specific.c
===================================================================
--- branches/uClibc-nptl/libpthread/linuxthreads/specific.c	2009-03-12 20:29:24 UTC (rev 25636)
+++ branches/uClibc-nptl/libpthread/linuxthreads/specific.c	2009-03-12 20:56:23 UTC (rev 25637)
@@ -104,13 +104,14 @@
      that if the key is reallocated later by pthread_key_create, its
      associated values will be NULL in all threads.
 
-     If no threads have been created yet, clear it just in the
-     current thread.  */
+     If no threads have been created yet, or if we are exiting, clear
+     it just in the current thread.  */
 
   struct pthread_key_delete_helper_args args;
   args.idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
   args.idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
-  if (__pthread_manager_request != -1)
+  if (__pthread_manager_request != -1
+      && !(__builtin_expect (__pthread_exit_requested, 0)))
     {
       struct pthread_request request;
 
@@ -203,8 +204,9 @@
   __pthread_lock(THREAD_GETMEM(self, p_lock), self);
   for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) {
     if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) {
-      free(THREAD_GETMEM_NC(self, p_specific[i]));
+      void *p = THREAD_GETMEM_NC(self, p_specific[i]);
       THREAD_SETMEM_NC(self, p_specific[i], NULL);
+      free(p);
     }
   }
   __pthread_unlock(THREAD_GETMEM(self, p_lock));

Modified: branches/uClibc-nptl/libpthread/linuxthreads/spinlock.c
===================================================================
--- branches/uClibc-nptl/libpthread/linuxthreads/spinlock.c	2009-03-12 20:29:24 UTC (rev 25636)
+++ branches/uClibc-nptl/libpthread/linuxthreads/spinlock.c	2009-03-12 20:56:23 UTC (rev 25637)
@@ -637,8 +637,20 @@
 #if defined HAS_COMPARE_AND_SWAP
 	wait_node_dequeue(pp_head, pp_max_prio, p_max_prio);
 #endif
+
+      /* Release the spinlock *before* restarting.  */
+#if defined TEST_FOR_COMPARE_AND_SWAP
+      if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+	{
+	  __pthread_release(&lock->__spinlock);
+	}
+#endif
+
       restart(p_max_prio->thr);
-      break;
+
+      return;
     }
   }
 

Modified: branches/uClibc-nptl/libpthread/linuxthreads/spinlock.h
===================================================================
--- branches/uClibc-nptl/libpthread/linuxthreads/spinlock.h	2009-03-12 20:29:24 UTC (rev 25636)
+++ branches/uClibc-nptl/libpthread/linuxthreads/spinlock.h	2009-03-12 20:56:23 UTC (rev 25637)
@@ -172,7 +172,8 @@
 
 /* Operations on pthread_atomic, which is defined in internals.h */
 
-static __inline__ long atomic_increment(struct pthread_atomic *pa)
+static __inline__ long
+pthread_atomic_increment (struct pthread_atomic *pa)
 {
     long oldval;
 
@@ -184,7 +185,8 @@
 }
 
 
-static __inline__ long atomic_decrement(struct pthread_atomic *pa)
+static __inline__ long
+pthread_atomic_decrement (struct pthread_atomic *pa)
 {
     long oldval;
 

Modified: branches/uClibc-nptl/libpthread/linuxthreads/sysdeps/i386/tls.h
===================================================================
--- branches/uClibc-nptl/libpthread/linuxthreads/sysdeps/i386/tls.h	2009-03-12 20:29:24 UTC (rev 25636)
+++ branches/uClibc-nptl/libpthread/linuxthreads/sysdeps/i386/tls.h	2009-03-12 20:56:23 UTC (rev 25637)
@@ -46,9 +46,7 @@
   dtv_t *dtv;
   void *self;		/* Pointer to the thread descriptor.  */
   int multiple_threads;
-#ifdef NEED_DL_SYSINFO
   uintptr_t sysinfo;
-#endif
 } tcbhead_t;
 
 #else /* __ASSEMBLER__ */



More information about the uClibc-cvs mailing list