delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2013/02/17/22:39:02

X-Recipient: archive-cygwin AT delorie DOT com
X-SWARE-Spam-Status: No, hits=1.5 required=5.0 tests=AWL,BAYES_00,DKIM_ADSP_CUSTOM_MED,FREEMAIL_FROM,FSL_HELO_BARE_IP_2,NML_ADSP_CUSTOM_MED,RCVD_IN_DNSWL_NONE,RCVD_NUMERIC_HELO,RP_MATCHES_RCVD,SARE_SUB_ENC_UTF8,SPF_HELO_PASS
X-Spam-Check-By: sourceware.org
To: cygwin AT cygwin DOT com
From: Zach Saw <zach DOT saw AT gmail DOT com>
Subject: Weird threading / =?utf-8?b?X190aHJlYWQ=?= behavior
Date: Mon, 18 Feb 2013 03:38:27 +0000 (UTC)
Lines: 113
Message-ID: <loom.20130218T042711-4@post.gmane.org>
Mime-Version: 1.0
User-Agent: Loom/3.14 (http://gmane.org/)
X-IsSubscribed: yes
Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Id: <cygwin.cygwin.com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com

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;
   sleep(1);
   if (!test)
   {
      test = true; // *** comment this out for test #2
      TLS_data1 = gData->data1;
      TLS_data2 = gData->data2;
   }

   foo();
   return NULL;
}
 
void foo() {
   gResults[TLS_data1].data1 = TLS_data1;
   bar();
}
 
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)
         printf("failed\n");
     if (gResults[i].data2 != gData[i].data2)
         printf("failed\n");
  }
  
  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:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019