Home | History | Annotate | Download | only in memory_replay
      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