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

Bug#309193: /usr/bin/gcc: at runtime, TLS does not work, but at compile time, __thread does not give an error



> On Thu, May 19, 2005 at 10:41:31PM +0200, Jeroen N. Witmond wrote:
>> >
>> > Also, note that this is an unsound way to test for TLS.  The compiler,
>> > assembler, linker, C library, and on some platforms kernel must all
>> > support it.
>> >
>>
>> I am running debian/sarge (Linux DoornRoosje 2.4.26-1-386 #1 Tue Aug 24
>> 13:31:19 JST 2004 i686 GNU/Linux). The versions of gcc and libgcc1 are
>> in
>> my previous mail. Where can I find if Debian supports TLS on this
>> platform?
>
> It should work.  That's why I asked you for a test case.

Attached. 'make -LDFLAGS=-lpthread tls-temp; ./tls-temp;echo $?'. When
make succeeds (it should); '0' should be printed, but '2' is. Adding any
-ftls-model= does not change this.

>> Also, can you point me to a better way to test for TLS?
>
> TLS can be a runtime property, not a compile time one.  Runtime tests
> are seriously unwise in autoconf, though, so a compiler check is
> probably OK.  For instance, on MIPS the linker may be built with TLS
> support but the kernel may be missing the relevant trap handler.

TLS should be a runtime property for applications shipped in binary form;
when the application is built on the infrastructure that will run it, it
can be a compile time property (assuming you recompile afer changes in the
infrastructure, eg a kernel upgrade).  In fact, I have written an autoconf
macro based on the attached program to check for TLS at build time. The
program and the macro are based on parts of the source of valgrind
http://valgrind.org/ where the problem showed up in the regression test.
Any errors in the program and the macro are of course mine.

Jeroen.
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>

#define COUNT 10

static __thread int local;

/* Count need not be complete ... */
volatile static int errors_found = 0;

static const struct timespec awhile = { 0, 100000000 };

static void *tls_ptr(void *p)
{
  int *ip = (int*)p;
  int here = 0;
  int i;
  
  for(i = 0; i < COUNT; i++) {
    int a = (*ip)++;
    int b = here++;
    if (a != b || errors_found != 0) {
      errors_found++;	  
      return 0;
    }
    nanosleep(&awhile, 0);
  }
  
  return 0;
}

#define NTESTERS 2

int main()
{
  pthread_t threads[NTESTERS];
  int curthread = 0;
  static 
    int i;
  
  for(i = 0; i < NTESTERS; i++) {
    pthread_create(&threads[curthread++], NULL, tls_ptr, (void *)&local);
  }
  
  for(i = 0; i < curthread; i++)
    pthread_join(threads[i], NULL);
  
  return errors_found;
}

Reply to: