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 #include "perfetto/ext/base/file_utils.h"
19 #include "perfetto/ext/base/thread_task_runner.h"
20 #include "perfetto/tracing/internal/tracing_tls.h"
21 #include "perfetto/tracing/platform.h"
22 #include "perfetto/tracing/trace_writer_base.h"
23 
24 #include <pthread.h>
25 #include <stdlib.h>
26 
27 namespace perfetto {
28 
29 namespace {
30 
31 class PlatformPosix : public Platform {
32  public:
33   PlatformPosix();
34   ~PlatformPosix() override;
35 
36   ThreadLocalObject* GetOrCreateThreadLocalObject() override;
37   std::unique_ptr<base::TaskRunner> CreateTaskRunner(
38       const CreateTaskRunnerArgs&) override;
39   std::string GetCurrentProcessName() override;
40 
41  private:
42   pthread_key_t tls_key_{};
43 };
44 
45 // TODO(primiano): make base::ThreadTaskRunner directly inherit TaskRunner, so
46 // we can avoid this boilerplate.
47 class TaskRunnerInstance : public base::TaskRunner {
48  public:
49   TaskRunnerInstance();
50   ~TaskRunnerInstance() override;
51 
52   void PostTask(std::function<void()>) override;
53   void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override;
54   void AddFileDescriptorWatch(int fd, std::function<void()>) override;
55   void RemoveFileDescriptorWatch(int fd) override;
56   bool RunsTasksOnCurrentThread() const override;
57 
58  private:
59   base::ThreadTaskRunner thread_task_runner_;
60 };
61 
62 using ThreadLocalObject = Platform::ThreadLocalObject;
63 
PlatformPosix()64 PlatformPosix::PlatformPosix() {
65   auto tls_dtor = [](void* obj) {
66     delete static_cast<ThreadLocalObject*>(obj);
67   };
68   PERFETTO_CHECK(pthread_key_create(&tls_key_, tls_dtor) == 0);
69 }
70 
~PlatformPosix()71 PlatformPosix::~PlatformPosix() {
72   pthread_key_delete(tls_key_);
73 }
74 
GetOrCreateThreadLocalObject()75 ThreadLocalObject* PlatformPosix::GetOrCreateThreadLocalObject() {
76   // In chromium this should be implemented using base::ThreadLocalStorage.
77   auto tls = static_cast<ThreadLocalObject*>(pthread_getspecific(tls_key_));
78   if (!tls) {
79     tls = ThreadLocalObject::CreateInstance().release();
80     pthread_setspecific(tls_key_, tls);
81   }
82   return tls;
83 }
84 
CreateTaskRunner(const CreateTaskRunnerArgs &)85 std::unique_ptr<base::TaskRunner> PlatformPosix::CreateTaskRunner(
86     const CreateTaskRunnerArgs&) {
87   return std::unique_ptr<base::TaskRunner>(new TaskRunnerInstance());
88 }
89 
GetCurrentProcessName()90 std::string PlatformPosix::GetCurrentProcessName() {
91 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
92     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
93   std::string cmdline;
94   base::ReadFile("/proc/self/cmdline", &cmdline);
95   return cmdline.substr(0, cmdline.find('\0'));
96 #elif PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
97   return std::string(getprogname());
98 #else
99   return "unknown_producer";
100 #endif
101 }
102 
TaskRunnerInstance()103 TaskRunnerInstance::TaskRunnerInstance()
104     : thread_task_runner_(base::ThreadTaskRunner::CreateAndStart()) {}
105 TaskRunnerInstance::~TaskRunnerInstance() = default;
PostTask(std::function<void ()> func)106 void TaskRunnerInstance::PostTask(std::function<void()> func) {
107   thread_task_runner_.get()->PostTask(func);
108 }
109 
PostDelayedTask(std::function<void ()> func,uint32_t delay_ms)110 void TaskRunnerInstance::PostDelayedTask(std::function<void()> func,
111                                          uint32_t delay_ms) {
112   thread_task_runner_.get()->PostDelayedTask(func, delay_ms);
113 }
114 
AddFileDescriptorWatch(int fd,std::function<void ()> func)115 void TaskRunnerInstance::AddFileDescriptorWatch(int fd,
116                                                 std::function<void()> func) {
117   thread_task_runner_.get()->AddFileDescriptorWatch(fd, func);
118 }
119 
RemoveFileDescriptorWatch(int fd)120 void TaskRunnerInstance::RemoveFileDescriptorWatch(int fd) {
121   thread_task_runner_.get()->RemoveFileDescriptorWatch(fd);
122 }
123 
RunsTasksOnCurrentThread() const124 bool TaskRunnerInstance::RunsTasksOnCurrentThread() const {
125   return thread_task_runner_.get()->RunsTasksOnCurrentThread();
126 }
127 
128 }  // namespace
129 
130 // static
GetDefaultPlatform()131 Platform* Platform::GetDefaultPlatform() {
132   static PlatformPosix* instance = new PlatformPosix();
133   return instance;
134 }
135 
136 }  // namespace perfetto
137