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

Re: Library search path



Sorry for the late reply.

Daniel Jacobowitz <dan@debian.org> writes:

> On Tue, Nov 25, 2003 at 08:35:19PM +0100, Juergen Kreileder wrote:
>
> No.  /lib/ld-linux.so.2 _does_ support TLS.  It'll work fine, I've
> tested it.  "/lib/tls" is a red herring.

Ah yes, you're right.

> However if, as seems likely, the NV "TLS" libraries are dependent on
> NPTL then we need to do something different for them.

I think they're not.  glxinfo and glxgears run fine with
LD_ASSUME_KERNEL=2.4.1, ie. tls/libGL.so + LinuxThreads
(libpthread-0.10.so) works fine here.

There seem to be people with 2.4 kernels for which tls/libGL.so
doesn't work (see #219646).  NVIDIA's "tls_test" seems to return a
non-zero exit code for these people (I can't reproduce this, I get 0
on my 2.4.22 systems).

> That's why I said you could add the tag yourself.  Hmm, might be
> tricky to do.

I don't need to, I run a 2.6 kernel anyhow.
If sarge is going to use a 2.4 kernel by default there should be some
fix/work-around for problems like this, there might be more
problematic binaries than just the NVIDIA driver.


BTW, I see a problem with TLS on 2.6 kernels when running the appended
test code with LD_ASSUME_KERNEL < 2.6.  I'm not sure if it's related:

,----
| % gcc -Wall -D_GNU_SOURCE -pthread tls.c -o tls
| % ./tls
| BEFORE_BARRIER: primordial thread: tls_var is 0 (0x4000f8fc)
| BEFORE BARRIER: thread 1: test tls_var == 1 (0x40810bcc)
| BEFORE BARRIER: thread 2: test tls_var == 2 (0x41011bcc)
| BEFORE BARRIER: thread 3: test tls_var == 3 (0x41812bcc)
| BEFORE BARRIER: thread 4: test tls_var == 4 (0x42013bcc)
| BEFORE BARRIER: thread 5: test tls_var == 5 (0x42814bcc)
| AFTER BARRIER:  thread 1: test tls_var == 1 (0x40810bcc) OK
| AFTER BARRIER:  thread 2: test tls_var == 2 (0x41011bcc) OK
| AFTER BARRIER:  thread 5: test tls_var == 5 (0x42814bcc) OK
| AFTER BARRIER:  thread 3: test tls_var == 3 (0x41812bcc) OK
| AFTER BARRIER:  thread 4: test tls_var == 4 (0x42013bcc) OK
| AFTER BARRIER:  primordial thread: tls_var is 0 (0x4000f8fc) OK
`----

=> Without LD_ASSUME_KERNEL I get the expected output

,----
| % LD_ASSUME_KERNEL=2.4.1 ./tls 
| BEFORE_BARRIER: primordial thread: tls_var is 0 (0x400608bc)
| BEFORE BARRIER: thread 1: test tls_var == 1 (0x400608bc)
| BEFORE BARRIER: thread 2: test tls_var == 2 (0x400608bc)
| BEFORE BARRIER: thread 3: test tls_var == 3 (0x400608bc)
| BEFORE BARRIER: thread 4: test tls_var == 4 (0x400608bc)
| BEFORE BARRIER: thread 5: test tls_var == 5 (0x400608bc)
| AFTER BARRIER:  thread 1: test tls_var == 5 (0x400608bc) BROKEN
| AFTER BARRIER:  thread 2: test tls_var == 5 (0x400608bc) BROKEN
| AFTER BARRIER:  thread 3: test tls_var == 5 (0x400608bc) BROKEN
| AFTER BARRIER:  thread 5: test tls_var == 5 (0x400608bc) OK
| AFTER BARRIER:  thread 4: test tls_var == 5 (0x400608bc) BROKEN
| AFTER BARRIER:  primordial thread: tls_var is 5 (0x400608bc) BROKEN
`----

This looks broken: tls_var isn't thread local at all.  Thread 5 was
the last doing 'tls_var = i' and all other threads see this change.
Also note that tls_var address is the same in all threads.

Tested on three systems, all show the same behavior:
* unstable on dual PII, kernel 2.6.0-test10-mm1
* unstable on dual AthlonMP, kernel 2.6.0-test10-mm1
* testing on single AthlonXP, kernel 2.6.0-test11


        Juergen


#include <pthread.h>
#include <stdio.h>

#define THREADS 5

pthread_barrier_t barrier;
pthread_t threads[THREADS];

__thread int tls_var;

void *f(void *num)
{
    int i = (int) num;
    int value_before;

    tls_var = i;
    value_before = tls_var;
 
    printf("BEFORE BARRIER: thread %d: test tls_var == %d (%p)\n",
           i, tls_var, &tls_var);

    pthread_barrier_wait(&barrier);

    printf("AFTER BARRIER:  thread %d: test tls_var == %d (%p) %s\n",
           i, tls_var, &tls_var, tls_var == value_before ? "OK" : "BROKEN");

    return NULL;
}

int main(int argc, char *argv[])
{
    int i;
    int value_before;

    pthread_barrier_init(&barrier, NULL, THREADS);

    tls_var = 0;
    value_before = tls_var;

    printf("BEFORE_BARRIER: primordial thread: tls_var is %d (%p)\n",
           tls_var, &tls_var); 

    for (i = 0; i < THREADS; i++) {
        pthread_create(&threads[i], NULL, f, (void*) i + 1);
    }

    for (i = 0; i < THREADS; i++) {
        pthread_join(threads[i], NULL);
    }

    pthread_barrier_destroy(&barrier);

    printf("AFTER BARRIER:  primordial thread: tls_var is %d (%p) %s\n",
           tls_var, &tls_var, tls_var == value_before ? "OK" : "BROKEN");

    return 0;
}

-- 
Juergen Kreileder, Blackdown Java-Linux Team
http://www.blackdown.org/java-linux/java2-status/



Reply to: