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 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: 41 EndThreadAction() {} 42 43 bool EndThread() override { return true; } 44 45 uint64_t Execute(Pointers*) override { return 0; } 46 }; 47 48 class AllocAction : public Action { 49 public: 50 explicit 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: 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 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: 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 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: 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 108 bool DoesFree() override { return old_pointer_ != 0; } 109 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: 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 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: 155 explicit FreeAction(uintptr_t key_pointer) : AllocAction(key_pointer) { 156 } 157 158 bool DoesFree() override { return key_pointer_ != 0; } 159 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 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 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