1 /*
2  * Copyright (C) 2019 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/base/build_config.h"
18 
19 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
20     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
21     PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
22 
23 #include "perfetto/ext/base/file_utils.h"
24 #include "perfetto/ext/base/thread_task_runner.h"
25 #include "perfetto/tracing/internal/tracing_tls.h"
26 #include "perfetto/tracing/platform.h"
27 #include "perfetto/tracing/trace_writer_base.h"
28 
29 #include <pthread.h>
30 #include <stdlib.h>
31 
32 namespace perfetto {
33 
34 namespace {
35 
36 class PlatformPosix : public Platform {
37  public:
38   PlatformPosix();
39   ~PlatformPosix() override;
40 
41   ThreadLocalObject* GetOrCreateThreadLocalObject() override;
42   std::unique_ptr<base::TaskRunner> CreateTaskRunner(
43       const CreateTaskRunnerArgs&) override;
44   std::string GetCurrentProcessName() override;
45 
46  private:
47   pthread_key_t tls_key_{};
48 };
49 
50 using ThreadLocalObject = Platform::ThreadLocalObject;
51 
PlatformPosix()52 PlatformPosix::PlatformPosix() {
53   auto tls_dtor = [](void* obj) {
54     delete static_cast<ThreadLocalObject*>(obj);
55   };
56   PERFETTO_CHECK(pthread_key_create(&tls_key_, tls_dtor) == 0);
57 }
58 
~PlatformPosix()59 PlatformPosix::~PlatformPosix() {
60   pthread_key_delete(tls_key_);
61 }
62 
GetOrCreateThreadLocalObject()63 ThreadLocalObject* PlatformPosix::GetOrCreateThreadLocalObject() {
64   // In chromium this should be implemented using base::ThreadLocalStorage.
65   auto tls = static_cast<ThreadLocalObject*>(pthread_getspecific(tls_key_));
66   if (!tls) {
67     tls = ThreadLocalObject::CreateInstance().release();
68     pthread_setspecific(tls_key_, tls);
69   }
70   return tls;
71 }
72 
CreateTaskRunner(const CreateTaskRunnerArgs &)73 std::unique_ptr<base::TaskRunner> PlatformPosix::CreateTaskRunner(
74     const CreateTaskRunnerArgs&) {
75   return std::unique_ptr<base::TaskRunner>(
76       new base::ThreadTaskRunner(base::ThreadTaskRunner::CreateAndStart()));
77 }
78 
GetCurrentProcessName()79 std::string PlatformPosix::GetCurrentProcessName() {
80 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
81     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
82   std::string cmdline;
83   base::ReadFile("/proc/self/cmdline", &cmdline);
84   return cmdline.substr(0, cmdline.find('\0'));
85 #elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
86   return std::string(getprogname());
87 #else
88   return "unknown_producer";
89 #endif
90 }
91 
92 }  // namespace
93 
94 // static
GetDefaultPlatform()95 Platform* Platform::GetDefaultPlatform() {
96   static PlatformPosix* instance = new PlatformPosix();
97   return instance;
98 }
99 
100 }  // namespace perfetto
101 #endif  // OS_LINUX || OS_ANDROID || OS_APPLE
102