Weird threading / __thread behavior

Zach Saw
Mon Feb 18 03:38:00 GMT 2013

The following test case fails on Cygwin but passes on Linux (both tested using 
GCC 4.7.2). There are two failures that this test case exposes -- first without 
commenting out the line "test = true;" and the second is with it commented out. 
The first case shows the variable 'test' is not being treated as a threadlocal 
var. In the second case, test will pass but fail sporadically on multi-core 
machines. If you mask CPU affinity out to enable just one core, it will pass 
100% of the time. It shows a separate problem to case #1 (i.e. multithreaded 
apps will not run reliably on Cygwin). On my machine (Core2Duo), it fails on 
average once out of 5 runs.

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

void foo(void);  /* Functions that use the TLS data */
void bar(void);
#define checkResults(string, val) {             \
 if (val) {                                     \
   printf("Failed with %d at %s", val, string); \
   exit(1);                                     \
 }                                              \
__thread int TLS_data1 = 0;
__thread int TLS_data2 = 0;
__thread bool test = false;
#define                 NUMTHREADS   20 

typedef struct {
   int   data1;
   int   data2;
} threadparm_t; 

threadparm_t          gResults[NUMTHREADS];

void *theThread(void *parm)
   int               rc;
   threadparm_t     *gData;

   gData = (threadparm_t *)parm;
   if (!test)
      test = true; // *** comment this out for test #2
      TLS_data1 = gData->data1;
      TLS_data2 = gData->data2;

   return NULL;
void foo() {
   gResults[TLS_data1].data1 = TLS_data1;
void bar() {
   gResults[TLS_data1].data2 = TLS_data2;

int main(int argc, char **argv)
  pthread_t             thread[NUMTHREADS];
  int                   rc=0;
  int                   i;
  threadparm_t          gData[NUMTHREADS];
  printf("Enter Testcase - %s\n", argv[0]);
  for (i=0; i < NUMTHREADS; i++) {
     gResults[i].data1 = 0;
     gResults[i].data2 = 0;
  printf("Create/start threads\n");
  for (i=0; i < NUMTHREADS; i++) { 
     /* Create per-thread TLS data and pass it to the thread */
     gData[i].data1 = i;
     gData[i].data2 = (i+1)*2;
     printf("%d %d\n", gData[i].data1, gData[i].data2);
     rc = pthread_create(&thread[i], NULL, theThread, &gData[i]);
     checkResults("pthread_create()\n", rc);
  printf("Wait for the threads to complete, and release their resources\n");
  for (i=0; i < NUMTHREADS; i++) {
     rc = pthread_join(thread[i], NULL);
     checkResults("pthread_join()\n", rc);

  for (i=0; i < NUMTHREADS; i++) {
     printf("gResults, data=%d %d\n",
          gResults[i].data1, gResults[i].data2);
     if (gResults[i].data1 != gData[i].data1)
     if (gResults[i].data2 != gData[i].data2)
  printf("Main completed\n");
  return 0;

Compile with: g++ tls_test.cpp -o tls_test.exe -lpthread

Expected run outcome: no "failed" messages.

Problem reports:
Unsubscribe info:

More information about the Cygwin mailing list