• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 <inttypes.h>
18 #include <malloc.h>
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/param.h>
24 #include <time.h>
25 
26 #include <new>
27 
28 #include "Action.h"
29 #include "Threads.h"
30 #include "Pointers.h"
31 
nanotime()32 static uint64_t nanotime() {
33   struct timespec t;
34   t.tv_sec = t.tv_nsec = 0;
35   clock_gettime(CLOCK_MONOTONIC, &t);
36   return static_cast<uint64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
37 }
38 
39 class EndThreadAction : public Action {
40  public:
EndThreadAction()41   EndThreadAction() {}
42 
EndThread()43   bool EndThread() override { return true; }
44 
Execute(Pointers *)45   uint64_t Execute(Pointers*) override { return 0; }
46 };
47 
48 class AllocAction : public Action {
49  public:
AllocAction(uintptr_t key_pointer)50   AllocAction(uintptr_t key_pointer) : key_pointer_(key_pointer) {}
51 
52  protected:
53   uintptr_t key_pointer_ = 0;
54   size_t size_ = 0;
55 };
56 
57 class MallocAction : public AllocAction {
58  public:
MallocAction(uintptr_t key_pointer,const char * line)59   MallocAction(uintptr_t key_pointer, const char* line) : AllocAction(key_pointer) {
60     if (sscanf(line, "%zu", &size_) != 1) {
61       is_error_ = true;
62     }
63   }
64 
Execute(Pointers * pointers)65   uint64_t Execute(Pointers* pointers) override {
66     uint64_t time_nsecs = nanotime();
67     void* memory = malloc(size_);
68     time_nsecs = nanotime() - time_nsecs;
69 
70     memset(memory, 1, size_);
71     pointers->Add(key_pointer_, memory);
72 
73     return time_nsecs;
74   }
75 };
76 
77 class CallocAction : public AllocAction {
78  public:
CallocAction(uintptr_t key_pointer,const char * line)79   CallocAction(uintptr_t key_pointer, const char* line) : AllocAction(key_pointer) {
80     if (sscanf(line, "%zu %zu", &n_elements_, &size_) != 2) {
81       is_error_ = true;
82     }
83   }
84 
Execute(Pointers * pointers)85   uint64_t Execute(Pointers* pointers) override {
86     uint64_t time_nsecs = nanotime();
87     void* memory = calloc(n_elements_, size_);
88     time_nsecs = nanotime() - time_nsecs;
89 
90     memset(memory, 0, n_elements_ * size_);
91     pointers->Add(key_pointer_, memory);
92 
93     return time_nsecs;
94   }
95 
96  private:
97   size_t n_elements_ = 0;
98 };
99 
100 class ReallocAction : public AllocAction {
101  public:
ReallocAction(uintptr_t key_pointer,const char * line)102   ReallocAction(uintptr_t key_pointer, const char* line) : AllocAction(key_pointer) {
103     if (sscanf(line, "%" SCNxPTR " %zu", &old_pointer_, &size_) != 2) {
104       is_error_ = true;
105     }
106   }
107 
DoesFree()108   bool DoesFree() override { return old_pointer_ != 0; }
109 
Execute(Pointers * pointers)110   uint64_t Execute(Pointers* pointers) override {
111     void* old_memory = nullptr;
112     if (old_pointer_ != 0) {
113       old_memory = pointers->Remove(old_pointer_);
114     }
115 
116     uint64_t time_nsecs = nanotime();
117     void* memory = realloc(old_memory, size_);
118     time_nsecs = nanotime() - time_nsecs;
119 
120     memset(memory, 1, size_);
121     pointers->Add(key_pointer_, memory);
122 
123     return time_nsecs;
124   }
125 
126  private:
127   uintptr_t old_pointer_ = 0;
128 };
129 
130 class MemalignAction : public AllocAction {
131  public:
MemalignAction(uintptr_t key_pointer,const char * line)132   MemalignAction(uintptr_t key_pointer, const char* line) : AllocAction(key_pointer) {
133     if (sscanf(line, "%zu %zu", &align_, &size_) != 2) {
134       is_error_ = true;
135     }
136   }
137 
Execute(Pointers * pointers)138   uint64_t Execute(Pointers* pointers) override {
139     uint64_t time_nsecs = nanotime();
140     void* memory = memalign(align_, size_);
141     time_nsecs = nanotime() - time_nsecs;
142 
143     memset(memory, 1, size_);
144     pointers->Add(key_pointer_, memory);
145 
146     return time_nsecs;
147   }
148 
149  private:
150   size_t align_ = 0;
151 };
152 
153 class FreeAction : public AllocAction {
154  public:
FreeAction(uintptr_t key_pointer)155   FreeAction(uintptr_t key_pointer) : AllocAction(key_pointer) {
156   }
157 
DoesFree()158   bool DoesFree() override { return key_pointer_ != 0; }
159 
Execute(Pointers * pointers)160   uint64_t Execute(Pointers* pointers) override {
161     if (key_pointer_) {
162       void* memory = pointers->Remove(key_pointer_);
163       uint64_t time_nsecs = nanotime();
164       free(memory);
165       return nanotime() - time_nsecs;
166     }
167     return 0;
168   }
169 };
170 
MaxActionSize()171 size_t Action::MaxActionSize() {
172   size_t max = MAX(sizeof(EndThreadAction), sizeof(MallocAction));
173   max = MAX(max, sizeof(CallocAction));
174   max = MAX(max, sizeof(ReallocAction));
175   max = MAX(max, sizeof(MemalignAction));
176   return MAX(max, sizeof(FreeAction));
177 }
178 
CreateAction(uintptr_t key_pointer,const char * type,const char * line,void * action_memory)179 Action* Action::CreateAction(uintptr_t key_pointer, const char* type,
180                              const char* line, void* action_memory) {
181   Action* action = nullptr;
182   if (strcmp(type, "malloc") == 0) {
183     action = new (action_memory) MallocAction(key_pointer, line);
184   } else if (strcmp(type, "free") == 0) {
185     action = new (action_memory) FreeAction(key_pointer);
186   } else if (strcmp(type, "calloc") == 0) {
187     action = new (action_memory) CallocAction(key_pointer, line);
188   } else if (strcmp(type, "realloc") == 0) {
189     action = new (action_memory) ReallocAction(key_pointer, line);
190   } else if (strcmp(type, "memalign") == 0) {
191     action = new (action_memory) MemalignAction(key_pointer, line);
192   } else if (strcmp(type, "thread_done") == 0) {
193     action = new (action_memory) EndThreadAction();
194   }
195 
196   if (action == nullptr || action->IsError()) {
197     return nullptr;
198   }
199   return action;
200 }
201