17656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh/* 27656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh * Copyright (C) 2015 The Android Open Source Project 37656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh * 47656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh * Licensed under the Apache License, Version 2.0 (the "License"); 57656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh * you may not use this file except in compliance with the License. 67656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh * You may obtain a copy of the License at 77656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh * 87656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh * http://www.apache.org/licenses/LICENSE-2.0 97656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh * 107656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh * Unless required by applicable law or agreed to in writing, software 117656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh * distributed under the License is distributed on an "AS IS" BASIS, 127656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh * See the License for the specific language governing permissions and 147656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh * limitations under the License. 157656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh */ 167656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 177656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh#include <gtest/gtest.h> 1883380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh#include <stdint.h> 1983380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh#include <string.h> 207656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 215058a005b8dfb4bd5eefe0eb4420f1c37665b2b0Chih-Hung Hsieh#if defined(__GNUC__) && !defined(__clang__) && \ 225058a005b8dfb4bd5eefe0eb4420f1c37665b2b0Chih-Hung Hsieh (defined(__arm__) || defined(__aarch64__)) 237656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh// Gcc has a bug with -O -fdata-section for the arm target: http://b/22772147. 247656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh// Until that bug is fixed, disable optimization since 257656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh// it is not essential for this test. 267656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh#pragma GCC optimize("-O0") 277656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh#endif 287656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 297656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh__thread int local_var = 100; 307656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsiehint shared_var = 200; 317656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 327656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsiehstatic void reset_vars() { 337656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh local_var = 1000; 347656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh shared_var = 2000; 357656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh // local_var should be reset by threads 367656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh} 377656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 387656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsiehtypedef void* (*MyThread)(void*); 397656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 407656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsiehstatic void* inc_shared_var(void* p) { 417656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh int *data = reinterpret_cast<int*>(p); 427656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh shared_var++; 437656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh *data = shared_var; 447656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh return nullptr; 457656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh} 467656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 477656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsiehstatic void* inc_local_var(void* p) { 487656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh int *data = reinterpret_cast<int*>(p); 497656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh local_var++; 507656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh *data = local_var; 517656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh return nullptr; 527656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh} 537656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 547656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsiehstatic int run_one_thread(MyThread foo) { 557656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh pthread_t t; 567656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh int data; 577656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh int error = pthread_create(&t, nullptr, foo, &data); 587656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh if (!error) 597656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh error = pthread_join(t, nullptr); 607656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh return error ? error : data; 617656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh} 627656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 637656d0cec0509f73705da222a2389b00031097d8Chih-Hung HsiehTEST(thread_local_storage, shared) { 647656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh reset_vars(); 657656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_var, 1000); 667656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_var, 2000); 677656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 687656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh // Update shared_var, local_var remains 1000. 697656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(run_one_thread(inc_shared_var), 2001); 707656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_var, 1000); 717656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_var, 2001); 727656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 737656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(run_one_thread(inc_shared_var), 2002); 747656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_var, 1000); 757656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_var, 2002); 767656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 777656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(run_one_thread(inc_shared_var), 2003); 787656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_var, 1000); 797656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_var, 2003); 807656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh} 817656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 827656d0cec0509f73705da222a2389b00031097d8Chih-Hung HsiehTEST(thread_local_storage, local) { 837656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh reset_vars(); 847656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_var, 1000); 857656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_var, 2000); 867656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 877656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh // When a child thread updates its own TLS variable, 887656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh // this thread's local_var and shared_var are not changed. 897656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh // TLS local_var is initialized to 100 in a thread. 907656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(run_one_thread(inc_local_var), 101); 917656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_var, 1000); 927656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_var, 2000); 937656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 947656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(run_one_thread(inc_local_var), 101); 957656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_var, 1000); 967656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_var, 2000); 977656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 987656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(run_one_thread(inc_local_var), 101); 997656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_var, 1000); 1007656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_var, 2000); 1017656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh} 1027656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 1037656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh// Test TLS initialization of more complicated type, array of struct. 1047656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsiehstruct Point { 1057656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh int x, y; 1067656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh}; 1077656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 1087656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsiehtypedef Point Triangle[3]; 1097656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 1107656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh__thread Triangle local_triangle = {{10,10}, {20,20}, {30,30}}; 1117656d0cec0509f73705da222a2389b00031097d8Chih-Hung HsiehTriangle shared_triangle = {{1,1}, {2,2}, {3,3}}; 1127656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 1137656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsiehstatic void reset_triangle() { 1147656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh static const Triangle t1 = {{3,3}, {4,4}, {5,5}}; 1157656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh static const Triangle t2 = {{2,2}, {3,3}, {4,4}}; 1167656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh memcpy(local_triangle, t1, sizeof(local_triangle)); 1177656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh memcpy(shared_triangle, t2, sizeof(shared_triangle)); 1187656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh} 1197656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 1207656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsiehstatic void* move_shared_triangle(void* p) { 1217656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh int *data = reinterpret_cast<int*>(p); 1227656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh shared_triangle[1].y++; 1237656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh *data = shared_triangle[1].y; 1247656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh return nullptr; 1257656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh} 1267656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 1277656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsiehstatic void* move_local_triangle(void* p) { 1287656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh int *data = reinterpret_cast<int*>(p); 1297656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh local_triangle[1].y++; 1307656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh *data = local_triangle[1].y; 1317656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh return nullptr; 1327656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh} 1337656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 1347656d0cec0509f73705da222a2389b00031097d8Chih-Hung HsiehTEST(thread_local_storage, shared_triangle) { 1357656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh reset_triangle(); 1367656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_triangle[1].y, 4); 1377656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_triangle[1].y, 3); 1387656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 1397656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh // Update shared_triangle, local_triangle remains 1000. 1407656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(run_one_thread(move_shared_triangle), 4); 1417656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_triangle[1].y, 4); 1427656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_triangle[1].y, 4); 1437656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 1447656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(run_one_thread(move_shared_triangle), 5); 1457656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_triangle[1].y, 4); 1467656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_triangle[1].y, 5); 1477656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 1487656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(run_one_thread(move_shared_triangle), 6); 1497656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_triangle[1].y, 4); 1507656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_triangle[1].y, 6); 1517656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh} 1527656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 1537656d0cec0509f73705da222a2389b00031097d8Chih-Hung HsiehTEST(thread_local_storage, local_triangle) { 1547656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh reset_triangle(); 1557656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_triangle[1].y, 4); 1567656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_triangle[1].y, 3); 1577656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 1587656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh // Update local_triangle, parent thread's 1597656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh // shared_triangle and local_triangle are unchanged. 1607656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(run_one_thread(move_local_triangle), 21); 1617656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_triangle[1].y, 4); 1627656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_triangle[1].y, 3); 1637656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 1647656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(run_one_thread(move_local_triangle), 21); 1657656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_triangle[1].y, 4); 1667656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_triangle[1].y, 3); 1677656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh 1687656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(run_one_thread(move_local_triangle), 21); 1697656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(local_triangle[1].y, 4); 1707656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh ASSERT_EQ(shared_triangle[1].y, 3); 1717656d0cec0509f73705da222a2389b00031097d8Chih-Hung Hsieh} 17283380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh 17383380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh// Test emutls runtime data structures and __emutls_get_address function. 17483380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsiehtypedef unsigned int gcc_word __attribute__((mode(word))); 17583380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsiehtypedef unsigned int gcc_pointer __attribute__((mode(pointer))); 17683380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsiehstruct gcc_emutls_object { // for libgcc 17783380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh gcc_word size; 17883380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh gcc_word align; 17983380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh union { 18083380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh gcc_pointer offset; 18183380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh void* ptr; 18283380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh } loc; 18383380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh void* templ; 18483380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh}; 18583380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh 18683380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsiehtypedef struct __emutls_control { // for clang/llvm 18783380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh size_t size; 18883380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh size_t align; 18983380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh union { 19083380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh uintptr_t index; 19183380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh void* address; 19283380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh } object; 19383380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh void* value; 19483380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh} __emutls_control; 19583380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh 19683380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung HsiehTEST(thread_local_storage, type_size) { 19783380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh static_assert(sizeof(size_t) == sizeof(gcc_word), 19883380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh "size_t != gcc_word"); 19983380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh static_assert(sizeof(uintptr_t) == sizeof(gcc_pointer), 20083380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh "uintptr_t != gcc_pointer"); 20183380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh static_assert(sizeof(uintptr_t) == sizeof(void*), 20283380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh "sizoeof(uintptr_t) != sizeof(void*)"); 20383380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh static_assert(sizeof(__emutls_control) == sizeof(struct gcc_emutls_object), 20483380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh "sizeof(__emutls_control) != sizeof(struct gcc_emutls_object)"); 20583380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh} 20683380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh 20783380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsiehextern "C" void* __emutls_get_address(__emutls_control*); 20883380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh 20983380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung HsiehTEST(thread_local_storage, init_value) { 21083380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh char tls_value1[] = "123456789"; 21183380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh char tls_value2[] = "abcdefghi"; 21283380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh constexpr size_t num_saved_values = 10; 21383380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh __emutls_control tls_var[num_saved_values]; 21483380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh size_t prev_index = 0; 21583380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh void* saved_gap[num_saved_values]; 21683380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh void* saved_p[num_saved_values]; 21783380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh ASSERT_TRUE(strlen(tls_value2) <= strlen(tls_value1)); 21883380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh __emutls_control c = 21983380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh {strlen(tls_value1) + 1, 1, {0}, tls_value1}; 22083380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh for (size_t n = 0; n < num_saved_values; n++) { 22183380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh memcpy(&tls_var[n], &c, sizeof(c)); 22283380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh tls_var[n].align = (1 << n); 22383380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh } 22483380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh for (size_t n = 0; n < num_saved_values; n++) { 22583380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh // Try to mess up malloc space so that the next malloc will not have the 22683380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh // required alignment, but __emutls_get_address should still return an 22783380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh // aligned address. 22883380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh saved_gap[n] = malloc(1); 22983380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh void* p = __emutls_get_address(&tls_var[n]); 23083380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh saved_p[n] = p; 23183380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh ASSERT_TRUE(p != nullptr); 23283380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh ASSERT_TRUE(tls_var[n].object.index != 0); 23383380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh // check if p is a new object. 23483380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh if (n > 0) { 23583380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh // In single-thread environment, object.address == p. 23683380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh // In multi-threads environment, object.index is increased. 23783380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh ASSERT_TRUE(prev_index + 1 == tls_var[n].object.index || 23883380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh p == tls_var[n].object.address); 23983380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh ASSERT_TRUE(p != saved_p[n - 1]); 24083380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh } 24183380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh prev_index = tls_var[n].object.index; 24283380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh // check if p is aligned 24383380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh uintptr_t align = (1 << n); 24483380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh uintptr_t address= reinterpret_cast<uintptr_t>(p); 24583380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh ASSERT_EQ((address & ~(align - 1)), address); 24683380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh // check if *p is initialized 24783380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh ASSERT_STREQ(tls_value1, static_cast<char*>(p)); 24883380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh // change value in *p 24983380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh memcpy(p, tls_value2, strlen(tls_value2) + 1); 25083380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh } 25183380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh for (size_t n = 0; n < num_saved_values; n++) { 25283380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh free(saved_gap[n]); 25383380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh } 25483380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh for (size_t n = 0; n < num_saved_values; n++) { 25583380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh void* p = __emutls_get_address(&tls_var[n]); 25683380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh ASSERT_EQ(p, saved_p[n]); 25783380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh // check if *p has the new value 25883380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh ASSERT_STREQ(tls_value2, static_cast<char*>(p)); 25983380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh } 26083380b5cf05c9db5067c58cb01e67f282ef53b25Chih-Hung Hsieh} 261