Current-Users archive

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

Re: threaded programs report bogus process size ?



In article <h9u2f5$qap$1%serpens.de@localhost>,
Michael van Elst <mlelstv%serpens.de@localhost> wrote:
>njoly%pasteur.fr@localhost (Nicolas Joly) writes:
>
>>I just noticed that threaded processes may report increasing process
>>size of their life ...
>
>libpthread never frees the pthread data structure and associated
>thread stack when a thread ends but puts it onto a private queue
>("deadqueue") and reclaims it again when a new thread is created.
>
>The reclaim can fail when a new thread is created shortly after
>an old thread ended because of a race with the kernel. As a result
>a new thread is allocated.
>
>So _some_ leakage is allowed by design.
>
>The problem is that the reclaim operation is only tried for the
>thread that ended last (the top of the "deadqueue"). So in a
>tight pthread_create/join loop the leaked threads just pile up.
>
>To correct this the reclaim operation should loop over the queue
>and try to reclaim any of the dead threads.

This seems to fix it.


christos

Index: pthread.c
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread.c,v
retrieving revision 1.112
diff -u -u -r1.112 pthread.c
--- pthread.c   2 Jul 2009 09:59:00 -0000       1.112
+++ pthread.c   30 Sep 2009 00:12:20 -0000
@@ -316,7 +316,7 @@
 pthread_create(pthread_t *thread, const pthread_attr_t *attr,
            void *(*startfunc)(void *), void *arg)
 {
-       pthread_t newthread;
+       pthread_t newthread, first_thread;
        pthread_attr_t nattr;
        struct pthread_attr_private *p;
        char * volatile name;
@@ -353,8 +353,13 @@
         */
        if (!PTQ_EMPTY(&pthread__deadqueue)) {
                pthread_mutex_lock(&pthread__deadqueue_lock);
-               newthread = PTQ_FIRST(&pthread__deadqueue);
-               if (newthread != NULL) {
+               first_thread = PTQ_FIRST(&pthread__deadqueue);
+               newthread = first_thread;
+               do {
+                       if (newthread == NULL) {
+                               pthread_mutex_unlock(&pthread__deadqueue_lock);
+                               break;
+                       }
                        PTQ_REMOVE(&pthread__deadqueue, newthread, pt_deadq);
                        pthread_mutex_unlock(&pthread__deadqueue_lock);
                        /* Still running? */
@@ -366,10 +371,11 @@
                                PTQ_INSERT_TAIL(&pthread__deadqueue,
                                    newthread, pt_deadq);
                                pthread_mutex_unlock(&pthread__deadqueue_lock);
-                               newthread = NULL;
-                       }
-               } else
-                       pthread_mutex_unlock(&pthread__deadqueue_lock);
+                       } else
+                               break;
+                       pthread_mutex_lock(&pthread__deadqueue_lock);
+                       newthread = PTQ_FIRST(&pthread__deadqueue);
+               } while (newthread != first_thread);
        }
 
        /*



Home | Main Index | Thread Index | Old Index