2 * Copyright (C) 2015 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <gtest/gtest.h>
20 // Gcc has a bug with -O -fdata-section for the arm target: http://b/22772147.
21 // Until that bug is fixed, disable optimization since
22 // it is not essential for this test.
23 #pragma GCC optimize("-O0")
26 __thread int local_var = 100;
29 static void reset_vars() {
32 // local_var should be reset by threads
35 typedef void* (*MyThread)(void*);
37 static void* inc_shared_var(void* p) {
38 int *data = reinterpret_cast<int*>(p);
44 static void* inc_local_var(void* p) {
45 int *data = reinterpret_cast<int*>(p);
51 static int run_one_thread(MyThread foo) {
54 int error = pthread_create(&t, nullptr, foo, &data);
56 error = pthread_join(t, nullptr);
57 return error ? error : data;
60 TEST(thread_local_storage, shared) {
62 ASSERT_EQ(local_var, 1000);
63 ASSERT_EQ(shared_var, 2000);
65 // Update shared_var, local_var remains 1000.
66 ASSERT_EQ(run_one_thread(inc_shared_var), 2001);
67 ASSERT_EQ(local_var, 1000);
68 ASSERT_EQ(shared_var, 2001);
70 ASSERT_EQ(run_one_thread(inc_shared_var), 2002);
71 ASSERT_EQ(local_var, 1000);
72 ASSERT_EQ(shared_var, 2002);
74 ASSERT_EQ(run_one_thread(inc_shared_var), 2003);
75 ASSERT_EQ(local_var, 1000);
76 ASSERT_EQ(shared_var, 2003);
79 TEST(thread_local_storage, local) {
81 ASSERT_EQ(local_var, 1000);
82 ASSERT_EQ(shared_var, 2000);
84 // When a child thread updates its own TLS variable,
85 // this thread's local_var and shared_var are not changed.
86 // TLS local_var is initialized to 100 in a thread.
87 ASSERT_EQ(run_one_thread(inc_local_var), 101);
88 ASSERT_EQ(local_var, 1000);
89 ASSERT_EQ(shared_var, 2000);
91 ASSERT_EQ(run_one_thread(inc_local_var), 101);
92 ASSERT_EQ(local_var, 1000);
93 ASSERT_EQ(shared_var, 2000);
95 ASSERT_EQ(run_one_thread(inc_local_var), 101);
96 ASSERT_EQ(local_var, 1000);
97 ASSERT_EQ(shared_var, 2000);
100 // Test TLS initialization of more complicated type, array of struct.
105 typedef Point Triangle[3];
107 __thread Triangle local_triangle = {{10,10}, {20,20}, {30,30}};
108 Triangle shared_triangle = {{1,1}, {2,2}, {3,3}};
110 static void reset_triangle() {
111 static const Triangle t1 = {{3,3}, {4,4}, {5,5}};
112 static const Triangle t2 = {{2,2}, {3,3}, {4,4}};
113 memcpy(local_triangle, t1, sizeof(local_triangle));
114 memcpy(shared_triangle, t2, sizeof(shared_triangle));
117 static void* move_shared_triangle(void* p) {
118 int *data = reinterpret_cast<int*>(p);
119 shared_triangle[1].y++;
120 *data = shared_triangle[1].y;
124 static void* move_local_triangle(void* p) {
125 int *data = reinterpret_cast<int*>(p);
126 local_triangle[1].y++;
127 *data = local_triangle[1].y;
131 TEST(thread_local_storage, shared_triangle) {
133 ASSERT_EQ(local_triangle[1].y, 4);
134 ASSERT_EQ(shared_triangle[1].y, 3);
136 // Update shared_triangle, local_triangle remains 1000.
137 ASSERT_EQ(run_one_thread(move_shared_triangle), 4);
138 ASSERT_EQ(local_triangle[1].y, 4);
139 ASSERT_EQ(shared_triangle[1].y, 4);
141 ASSERT_EQ(run_one_thread(move_shared_triangle), 5);
142 ASSERT_EQ(local_triangle[1].y, 4);
143 ASSERT_EQ(shared_triangle[1].y, 5);
145 ASSERT_EQ(run_one_thread(move_shared_triangle), 6);
146 ASSERT_EQ(local_triangle[1].y, 4);
147 ASSERT_EQ(shared_triangle[1].y, 6);
150 TEST(thread_local_storage, local_triangle) {
152 ASSERT_EQ(local_triangle[1].y, 4);
153 ASSERT_EQ(shared_triangle[1].y, 3);
155 // Update local_triangle, parent thread's
156 // shared_triangle and local_triangle are unchanged.
157 ASSERT_EQ(run_one_thread(move_local_triangle), 21);
158 ASSERT_EQ(local_triangle[1].y, 4);
159 ASSERT_EQ(shared_triangle[1].y, 3);
161 ASSERT_EQ(run_one_thread(move_local_triangle), 21);
162 ASSERT_EQ(local_triangle[1].y, 4);
163 ASSERT_EQ(shared_triangle[1].y, 3);
165 ASSERT_EQ(run_one_thread(move_local_triangle), 21);
166 ASSERT_EQ(local_triangle[1].y, 4);
167 ASSERT_EQ(shared_triangle[1].y, 3);