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