• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 #include "perfetto/tracing/platform.h"
18 
19 #include <atomic>
20 
21 #include "perfetto/base/task_runner.h"
22 #include "perfetto/ext/base/waitable_event.h"
23 #include "perfetto/tracing/internal/tracing_tls.h"
24 #include "test/gtest_and_gmock.h"
25 
26 namespace perfetto {
27 namespace {
28 
GetTLS()29 internal::TracingTLS* GetTLS() {
30   return static_cast<internal::TracingTLS*>(
31       Platform::GetDefaultPlatform()->GetOrCreateThreadLocalObject());
32 }
33 
34 // We use this class only as a listener to detect thread-local destruction.
35 class FakeTraceWriter : public TraceWriterBase {
36  public:
37   std::atomic<bool>* destroyed_flag;
38 
~FakeTraceWriter()39   ~FakeTraceWriter() override { *destroyed_flag = true; }
NewTracePacket()40   protozero::MessageHandle<protos::pbzero::TracePacket> NewTracePacket()
41       override {
42     PERFETTO_CHECK(false);
43   }
FinishTracePacket()44   void FinishTracePacket() override { PERFETTO_CHECK(false); }
Flush(std::function<void ()>)45   void Flush(std::function<void()>) override {}
written() const46   uint64_t written() const override { return 0; }
47 };
48 
49 // This test mainly checks that the thread at-exit logic works properly and
50 // destroys the TracingTLS when a thread exits.
TEST(PlatformUnittest,ThreadingAndTLSDtor)51 TEST(PlatformUnittest, ThreadingAndTLSDtor) {
52   auto* platform = Platform::GetDefaultPlatform();
53   if (!platform)
54     GTEST_SKIP() << "Platform::GetDefaultPlatform() not implemented";
55 
56   auto proc_name = platform->GetCurrentProcessName();
57   EXPECT_FALSE(proc_name.empty());
58 
59   // Create two threads.
60 
61   Platform::CreateTaskRunnerArgs tr_args{};
62   auto thread1 = platform->CreateTaskRunner(tr_args);
63   ASSERT_TRUE(thread1);
64 
65   auto thread2 = platform->CreateTaskRunner(tr_args);
66   ASSERT_TRUE(thread2);
67 
68   // Check that the TLS is actually thread-local.
69 
70   thread1->PostTask([] { GetTLS()->generation = 101; });
71   thread2->PostTask([] { GetTLS()->generation = 102; });
72   std::atomic<bool> thread1_destroyed{};
73   std::atomic<bool> thread2_destroyed{};
74 
75   // Now post another task on each thread. The task will:
76   // 1. Check that the generation matches what previously set.
77   // 2. Create a FakeTraceWriter and wire up a destruction event.
78   base::WaitableEvent evt1;
79   thread1->PostTask([&] {
80     EXPECT_EQ(GetTLS()->generation, 101u);
81     GetTLS()->data_sources_tls[0].per_instance[0].Reset();
82     std::unique_ptr<FakeTraceWriter> tw(new FakeTraceWriter());
83     tw->destroyed_flag = &thread1_destroyed;
84     GetTLS()->data_sources_tls[0].per_instance[0].trace_writer = std::move(tw);
85     evt1.Notify();
86   });
87   evt1.Wait();
88 
89   base::WaitableEvent evt2;
90   thread2->PostTask([&] {
91     EXPECT_EQ(GetTLS()->generation, 102u);
92     GetTLS()->data_sources_tls[0].per_instance[0].Reset();
93     std::unique_ptr<FakeTraceWriter> tw(new FakeTraceWriter());
94     tw->destroyed_flag = &thread2_destroyed;
95     GetTLS()->data_sources_tls[0].per_instance[0].trace_writer = std::move(tw);
96     evt2.Notify();
97   });
98   evt2.Wait();
99 
100   EXPECT_FALSE(thread1_destroyed);
101   EXPECT_FALSE(thread2_destroyed);
102 
103   thread1.reset();
104   EXPECT_TRUE(thread1_destroyed);
105   EXPECT_FALSE(thread2_destroyed);
106 
107   thread2.reset();
108   EXPECT_TRUE(thread2_destroyed);
109 }
110 
111 }  // namespace
112 }  // namespace perfetto
113