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 Subject: Weird threading / =?utf-8?b?X190aHJlYWQ=?= behavior Date: Mon, 18 Feb 2013 03:38:27 +0000 (UTC) Lines: 113 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit 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: List-Subscribe: List-Archive: List-Post: List-Help: , 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 #include #include #include 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