156 lines · cpp
1//===-- tsan_posix.cpp ----------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of ThreadSanitizer (TSan), a race detector.10//11//===----------------------------------------------------------------------===//12#include "tsan_interface.h"13#include "tsan_posix_util.h"14#include "tsan_test_util.h"15#include "gtest/gtest.h"16#include <pthread.h>17 18struct thread_key {19 pthread_key_t key;20 pthread_mutex_t *mtx;21 int val;22 int *cnt;23 thread_key(pthread_key_t key, pthread_mutex_t *mtx, int val, int *cnt)24 : key(key)25 , mtx(mtx)26 , val(val)27 , cnt(cnt) {28 }29};30 31static void thread_secific_dtor(void *v) {32 thread_key *k = (thread_key *)v;33 EXPECT_EQ(__interceptor_pthread_mutex_lock(k->mtx), 0);34 (*k->cnt)++;35 __tsan_write4(&k->cnt);36 EXPECT_EQ(__interceptor_pthread_mutex_unlock(k->mtx), 0);37 if (k->val == 42) {38 // Okay.39 } else if (k->val == 43 || k->val == 44) {40 k->val--;41 EXPECT_EQ(pthread_setspecific(k->key, k), 0);42 } else {43 ASSERT_TRUE(false);44 }45}46 47static void *dtors_thread(void *p) {48 thread_key *k = (thread_key *)p;49 EXPECT_EQ(pthread_setspecific(k->key, k), 0);50 return 0;51}52 53TEST(Posix, ThreadSpecificDtors) {54 int cnt = 0;55 pthread_key_t key;56 EXPECT_EQ(pthread_key_create(&key, thread_secific_dtor), 0);57 pthread_mutex_t mtx;58 EXPECT_EQ(__interceptor_pthread_mutex_init(&mtx, 0), 0);59 pthread_t th[3];60 thread_key k1 = thread_key(key, &mtx, 42, &cnt);61 thread_key k2 = thread_key(key, &mtx, 43, &cnt);62 thread_key k3 = thread_key(key, &mtx, 44, &cnt);63 EXPECT_EQ(__interceptor_pthread_create(&th[0], 0, dtors_thread, &k1), 0);64 EXPECT_EQ(__interceptor_pthread_create(&th[1], 0, dtors_thread, &k2), 0);65 EXPECT_EQ(__interceptor_pthread_join(th[0], 0), 0);66 EXPECT_EQ(__interceptor_pthread_create(&th[2], 0, dtors_thread, &k3), 0);67 EXPECT_EQ(__interceptor_pthread_join(th[1], 0), 0);68 EXPECT_EQ(__interceptor_pthread_join(th[2], 0), 0);69 EXPECT_EQ(pthread_key_delete(key), 0);70 EXPECT_EQ(6, cnt);71}72 73#if !defined(__aarch64__) && !defined(__APPLE__)74static __thread int local_var;75 76static void *local_thread(void *p) {77 __tsan_write1(&local_var);78 __tsan_write1(&p);79 if (p == 0)80 return 0;81 const int kThreads = 4;82 pthread_t th[kThreads];83 for (int i = 0; i < kThreads; i++)84 EXPECT_EQ(__interceptor_pthread_create(&th[i], 0, local_thread,85 (void *)((long)p - 1)),86 0);87 for (int i = 0; i < kThreads; i++)88 EXPECT_EQ(__interceptor_pthread_join(th[i], 0), 0);89 return 0;90}91#endif92 93TEST(Posix, ThreadLocalAccesses) {94// The test is failing with high thread count for aarch64.95// FIXME: track down the issue and re-enable the test.96// On Darwin, we're running unit tests without interceptors and __thread is97// using malloc and free, which causes false data race reports. On rare98// occasions on powerpc64le this test also fails.99#if !defined(__aarch64__) && !defined(__APPLE__) && !defined(powerpc64le)100 local_thread((void*)2);101#endif102}103 104struct CondContext {105 pthread_mutex_t m;106 pthread_cond_t c;107 int data;108};109 110static void *cond_thread(void *p) {111 CondContext &ctx = *static_cast<CondContext*>(p);112 113 EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0);114 EXPECT_EQ(ctx.data, 0);115 ctx.data = 1;116 EXPECT_EQ(__interceptor_pthread_cond_signal(&ctx.c), 0);117 EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0);118 119 EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0);120 while (ctx.data != 2)121 EXPECT_EQ(__interceptor_pthread_cond_wait(&ctx.c, &ctx.m), 0);122 EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0);123 124 EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0);125 ctx.data = 3;126 EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0);127 EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0);128 129 return 0;130}131 132TEST(Posix, CondBasic) {133 CondContext ctx;134 EXPECT_EQ(__interceptor_pthread_mutex_init(&ctx.m, 0), 0);135 EXPECT_EQ(__interceptor_pthread_cond_init(&ctx.c, 0), 0);136 ctx.data = 0;137 pthread_t th;138 EXPECT_EQ(__interceptor_pthread_create(&th, 0, cond_thread, &ctx), 0);139 140 EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0);141 while (ctx.data != 1)142 EXPECT_EQ(__interceptor_pthread_cond_wait(&ctx.c, &ctx.m), 0);143 ctx.data = 2;144 EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0);145 EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0);146 147 EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0);148 while (ctx.data != 3)149 EXPECT_EQ(__interceptor_pthread_cond_wait(&ctx.c, &ctx.m), 0);150 EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0);151 152 EXPECT_EQ(__interceptor_pthread_join(th, 0), 0);153 EXPECT_EQ(__interceptor_pthread_cond_destroy(&ctx.c), 0);154 EXPECT_EQ(__interceptor_pthread_mutex_destroy(&ctx.m), 0);155}156