15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//===-- tsan_posix.cc -----------------------------------------------------===// 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// The LLVM Compiler Infrastructure 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// License. See LICENSE.TXT for details. 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//===----------------------------------------------------------------------===// 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This file is a part of ThreadSanitizer (TSan), a race detector. 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//===----------------------------------------------------------------------===// 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "tsan_interface.h" 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "tsan_test_util.h" 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "gtest/gtest.h" 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <pthread.h> 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct thread_key { 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pthread_key_t key; 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pthread_mutex_t *mtx; 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int val; 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int *cnt; 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) thread_key(pthread_key_t key, pthread_mutex_t *mtx, int val, int *cnt) 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : key(key) 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , mtx(mtx) 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , val(val) 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , cnt(cnt) { 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void thread_secific_dtor(void *v) { 32f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu thread_key *k = (thread_key *)v; 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) EXPECT_EQ(pthread_mutex_lock(k->mtx), 0); 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (*k->cnt)++; 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) __tsan_write4(&k->cnt); 36e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) EXPECT_EQ(pthread_mutex_unlock(k->mtx), 0); 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (k->val == 42) { 3809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) delete k; 3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else if (k->val == 43 || k->val == 44) { 4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) k->val--; 4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) EXPECT_EQ(pthread_setspecific(k->key, k), 0); 4206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) } else { 4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ASSERT_TRUE(false); 4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 453c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch} 4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 471e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)static void *dtors_thread(void *p) { 481e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) thread_key *k = (thread_key *)p; 49d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(pthread_setspecific(k->key, k), 0); 5009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return 0; 51d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 52d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)TEST(Posix, ThreadSpecificDtors) { 5409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int cnt = 0; 5553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) pthread_key_t key; 5653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) EXPECT_EQ(pthread_key_create(&key, thread_secific_dtor), 0); 57a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) pthread_mutex_t mtx; 5853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) EXPECT_EQ(pthread_mutex_init(&mtx, 0), 0); 5919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) pthread_t th[3]; 6053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) thread_key *k[3]; 6153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) k[0] = new thread_key(key, &mtx, 42, &cnt); 6253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) k[1] = new thread_key(key, &mtx, 43, &cnt); 6353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) k[2] = new thread_key(key, &mtx, 44, &cnt); 6453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) EXPECT_EQ(pthread_create(&th[0], 0, dtors_thread, k[0]), 0); 6553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) EXPECT_EQ(pthread_create(&th[1], 0, dtors_thread, k[1]), 0); 6653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) EXPECT_EQ(pthread_join(th[0], 0), 0); 6751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) EXPECT_EQ(pthread_create(&th[2], 0, dtors_thread, k[2]), 0); 6853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) EXPECT_EQ(pthread_join(th[1], 0), 0); 6953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) EXPECT_EQ(pthread_join(th[2], 0), 0); 7053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) EXPECT_EQ(pthread_key_delete(key), 0); 7153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) EXPECT_EQ(6, cnt); 7209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 7353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 7453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static __thread int local_var; 7553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 76d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static void *local_thread(void *p) { 7753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) __tsan_write1(&local_var); 78aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch __tsan_write1(&p); 7953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (p == 0) 8053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return 0; 815267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) const int kThreads = 4; 82d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) pthread_t th[kThreads]; 8309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (int i = 0; i < kThreads; i++) 8407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch EXPECT_EQ(pthread_create(&th[i], 0, local_thread, 8553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) (void*)((long)p - 1)), 0); // NOLINT 8609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (int i = 0; i < kThreads; i++) 87a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch EXPECT_EQ(pthread_join(th[i], 0), 0); 8851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) return 0; 8951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)} 90a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 9109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)TEST(Posix, ThreadLocalAccesses) { 921e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) local_thread((void*)2); 93a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)} 941e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 951e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)struct CondContext { 961e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) pthread_mutex_t m; 971e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) pthread_cond_t c; 9809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int data; 991e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}; 10007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 101bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)static void *cond_thread(void *p) { 102a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) CondContext &ctx = *static_cast<CondContext*>(p); 103f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 104a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0); 105a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(ctx.data, 0); 106a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) ctx.data = 1; 10751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) EXPECT_EQ(pthread_cond_signal(&ctx.c), 0); 1081e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0); 1091e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 1101e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0); 1111e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) while (ctx.data != 2) 1121e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0); 1131e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0); 1141e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 115f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0); 116f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ctx.data = 3; 117f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0); 118a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0); 119f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 120f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu return 0; 121f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu} 122f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 123f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(Posix, CondBasic) { 124f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu CondContext ctx; 125f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_mutex_init(&ctx.m, 0), 0); 126f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_cond_init(&ctx.c, 0), 0); 127f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ctx.data = 0; 128f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu pthread_t th; 129f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_create(&th, 0, cond_thread, &ctx), 0); 130f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 131f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0); 132f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu while (ctx.data != 1) 133f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0); 134f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ctx.data = 2; 135f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0); 136f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0); 137f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 138f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0); 139f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu while (ctx.data != 3) 140f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0); 141f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0); 142f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 143f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_join(th, 0), 0); 144f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_cond_destroy(&ctx.c), 0); 145f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(pthread_mutex_destroy(&ctx.m), 0); 146f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu} 147f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu