1 /* Copyright 2020 Google LLC. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include "ruy/profiler/instrumentation.h"
17 
18 #ifdef RUY_PROFILER
19 
20 #include <cstring>
21 
22 namespace ruy {
23 namespace profiler {
24 
operator =(const Label & other)25 void Label::operator=(const Label& other) {
26   format_ = other.format_;
27   args_count_ = other.args_count_;
28   for (int i = 0; i < args_count_; i++) {
29     args_[i] = other.args_[i];
30   }
31 }
32 
operator ==(const Label & other) const33 bool Label::operator==(const Label& other) const {
34   if (std::string(format_) != std::string(other.format_)) {
35     return false;
36   }
37   if (args_count_ != other.args_count_) {
38     return false;
39   }
40   for (int i = 0; i < args_count_; i++) {
41     if (args_[i] != other.args_[i]) {
42       return false;
43     }
44   }
45   return true;
46 }
47 
Formatted() const48 std::string Label::Formatted() const {
49   static constexpr int kBufSize = 256;
50   char buf[kBufSize];
51   if (args_count_ == 0) {
52     return format_;
53   }
54   if (args_count_ == 1) {
55     snprintf(buf, kBufSize, format_, args_[0]);
56   } else if (args_count_ == 2) {
57     snprintf(buf, kBufSize, format_, args_[0], args_[1]);
58   } else if (args_count_ == 3) {
59     snprintf(buf, kBufSize, format_, args_[0], args_[1], args_[2]);
60   } else if (args_count_ == 4) {
61     snprintf(buf, kBufSize, format_, args_[0], args_[1], args_[2], args_[3]);
62   } else {
63     abort();
64   }
65   return buf;
66 }
67 
68 namespace detail {
69 
GlobalsMutex()70 std::mutex* GlobalsMutex() {
71   static std::mutex mutex;
72   return &mutex;
73 }
74 
GlobalIsProfilerRunning()75 bool& GlobalIsProfilerRunning() {
76   static bool b;
77   return b;
78 }
79 
GlobalAllThreadStacks()80 std::vector<ThreadStack*>* GlobalAllThreadStacks() {
81   static std::vector<ThreadStack*> all_stacks;
82   return &all_stacks;
83 }
84 
ThreadLocalThreadStack()85 ThreadStack* ThreadLocalThreadStack() {
86   thread_local static ThreadStack thread_stack;
87   return &thread_stack;
88 }
89 
ThreadStack()90 ThreadStack::ThreadStack() {
91   std::lock_guard<std::mutex> lock(*GlobalsMutex());
92   static std::uint32_t global_next_thread_stack_id = 0;
93   stack_.id = global_next_thread_stack_id++;
94   GlobalAllThreadStacks()->push_back(this);
95 }
96 
~ThreadStack()97 ThreadStack::~ThreadStack() {
98   std::lock_guard<std::mutex> lock(*GlobalsMutex());
99   std::vector<ThreadStack*>* all_stacks = GlobalAllThreadStacks();
100   for (auto it = all_stacks->begin(); it != all_stacks->end(); ++it) {
101     if (*it == this) {
102       all_stacks->erase(it);
103       return;
104     }
105   }
106 }
GetBufferSize(const Stack & stack)107 int GetBufferSize(const Stack& stack) {
108   return sizeof(stack.id) + sizeof(stack.size) +
109          stack.size * sizeof(stack.labels[0]);
110 }
111 
CopyToBuffer(const Stack & stack,char * dst)112 void CopyToBuffer(const Stack& stack, char* dst) {
113   memcpy(dst, &stack.id, sizeof(stack.id));
114   dst += sizeof(stack.id);
115   memcpy(dst, &stack.size, sizeof(stack.size));
116   dst += sizeof(stack.size);
117   memcpy(dst, stack.labels, stack.size * sizeof(stack.labels[0]));
118 }
119 
ReadFromBuffer(const char * src,Stack * stack)120 void ReadFromBuffer(const char* src, Stack* stack) {
121   memcpy(&stack->id, src, sizeof(stack->id));
122   src += sizeof(stack->id);
123   memcpy(&stack->size, src, sizeof(stack->size));
124   src += sizeof(stack->size);
125   memcpy(stack->labels, src, stack->size * sizeof(stack->labels[0]));
126 }
127 
128 }  // namespace detail
129 }  // namespace profiler
130 }  // namespace ruy
131 
132 #endif
133