Home | History | Annotate | Download | only in memtest
      1 /*
      2  * Copyright (C) 2013 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 <stdio.h>
     18 #include <stdlib.h>
     19 #include <string.h>
     20 #include <ctype.h>
     21 #include <sys/time.h>
     22 #include <time.h>
     23 #include <unistd.h>
     24 #include <sys/resource.h>
     25 #include <sys/syscall.h>
     26 #include <sys/types.h>
     27 #include <sys/mman.h>
     28 
     29 #include "memtest.h"
     30 
     31 nsecs_t system_time() {
     32     struct timespec t;
     33     t.tv_sec = t.tv_nsec = 0;
     34     clock_gettime(CLOCK_MONOTONIC, &t);
     35     return nsecs_t(t.tv_sec)*1000000000LL + t.tv_nsec;
     36 }
     37 
     38 static void usage(char* p) {
     39     printf("Usage: %s <test> <options>\n"
     40            "<test> is one of the following:\n"
     41            "  copy_bandwidth [--size BYTES_TO_COPY]\n"
     42            "  write_bandwidth [--size BYTES_TO_WRITE]\n"
     43            "  read_bandwidth [--size BYTES_TO_COPY]\n"
     44            "  per_core_bandwidth [--size BYTES]\n"
     45            "    --type copy_ldrd_strd | copy_ldmia_stmia | copy_vld1_vst1 |\n"
     46            "           copy_vldr_vstr | copy_vldmia_vstmia | memcpy | write_strd |\n"
     47            "           write_stmia | write_vst1 | write_vstr | write_vstmia | memset |\n"
     48            "           read_ldrd | read_ldmia | read_vld1 | read_vldr | read_vldmia\n"
     49            "  multithread_bandwidth [--size BYTES]\n"
     50            "    --type copy_ldrd_strd | copy_ldmia_stmia | copy_vld1_vst1 |\n"
     51            "           copy_vldr_vstr | copy_vldmia_vstmia | memcpy | write_strd |\n"
     52            "           write_stmia | write_vst1 | write_vstr | write_vstmia | memset |\n"
     53            "           read_ldrd | read_ldmia | read_vld1 | read_vldr | read_vldmia\n"
     54            "    --num_threads NUM_THREADS_TO_RUN\n"
     55            "  malloc [fill]\n"
     56            "  madvise\n"
     57            "  resampler\n"
     58            "  stack (stack smasher)\n"
     59            "  crawl\n"
     60            , p);
     61 }
     62 
     63 int copy_bandwidth(int argc, char** argv);
     64 int write_bandwidth(int argc, char** argv);
     65 int read_bandwidth(int argc, char** argv);
     66 int per_core_bandwidth(int argc, char** argv);
     67 int multithread_bandwidth(int argc, char** argv);
     68 int malloc_test(int argc, char** argv);
     69 int madvise_test(int argc, char** argv);
     70 int stack_smasher_test(int argc, char** argv);
     71 int crawl_test(int argc, char** argv);
     72 int fp_test(int argc, char** argv);
     73 
     74 typedef struct {
     75     const char *cmd_name;
     76     int (*func)(int argc, char** argv);
     77 } function_t;
     78 
     79 function_t function_table[] = {
     80     { "malloc", malloc_test },
     81     { "madvise", madvise_test },
     82     { "stack", stack_smasher_test },
     83     { "crawl", crawl_test },
     84     { "fp", fp_test },
     85     { "copy_bandwidth", copy_bandwidth },
     86     { "write_bandwidth", write_bandwidth },
     87     { "read_bandwidth", read_bandwidth },
     88     { "per_core_bandwidth", per_core_bandwidth },
     89     { "multithread_bandwidth", multithread_bandwidth },
     90 };
     91 
     92 int main(int argc, char** argv) {
     93     if (argc == 1) {
     94         usage(argv[0]);
     95         return 0;
     96     }
     97     int err = -1;
     98     for (unsigned int i = 0; i < sizeof(function_table)/sizeof(function_t); i++) {
     99         if (strcmp(argv[1], function_table[i].cmd_name) == 0) {
    100             err = (*function_table[i].func)(argc-1, argv+1);
    101             break;
    102         }
    103     }
    104     if (err) {
    105         usage(argv[0]);
    106     }
    107     return err;
    108 }
    109 
    110 int malloc_test(int argc, char** argv) {
    111     bool fill = (argc>=2 && !strcmp(argv[1], "fill"));
    112     size_t total = 0;
    113     size_t size = 0x40000000;
    114     while (size) {
    115         void* addr = malloc(size);
    116         if (addr == 0) {
    117             printf("size = %9zd failed\n", size);
    118             size >>= 1;
    119         } else {
    120             total += size;
    121             printf("size = %9zd, addr = %p (total = %9zd (%zd MB))\n",
    122                     size, addr, total, total / (1024*1024));
    123             if (fill) {
    124                 printf("filling...\n");
    125                 fflush(stdout);
    126                 memset(addr, 0, size);
    127             }
    128             size = size + (size>>1);
    129         }
    130     }
    131     printf("done. allocated %zd MB\n", total / (1024*1024));
    132     return 0;
    133 }
    134 
    135 int madvise_test(int, char**) {
    136     for (int i=0 ; i<2 ; i++) {
    137         size_t size = i==0 ? 4096 : 48*1024*1024; // 48 MB
    138         printf("Allocating %zd MB... ", size/(1024*1024)); fflush(stdout);
    139         void* addr1 = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    140         printf("%p (%s)\n", addr1, addr1==(void*)-1 ? "failed" : "OK"); fflush(stdout);
    141 
    142         printf("touching %p...\n", addr1); fflush(stdout);
    143         memset(addr1, 0x55, size);
    144 
    145         printf("advising DONTNEED...\n"); fflush(stdout);
    146         madvise(addr1, size, MADV_DONTNEED);
    147 
    148         printf("reading back %p...\n", addr1); fflush(stdout);
    149         if (*(long*)addr1 == 0) {
    150             printf("madvise freed some pages\n");
    151         } else if (*(long*)addr1 == 0x55555555) {
    152             printf("pages are still there\n");
    153         } else {
    154             printf("getting garbage back\n");
    155         }
    156 
    157         printf("Allocating %zd MB... ", size/(1024*1024)); fflush(stdout);
    158         void* addr2 = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    159         printf("%p (%s)\n", addr2, addr2==(void*)-1 ? "failed" : "OK"); fflush(stdout);
    160 
    161         printf("touching %p...\n", addr2); fflush(stdout);
    162         memset(addr2, 0xAA, size);
    163 
    164         printf("unmap %p ...\n", addr2); fflush(stdout);
    165         munmap(addr2, size);
    166 
    167         printf("touching %p...\n", addr1); fflush(stdout);
    168         memset(addr1, 0x55, size);
    169 
    170         printf("unmap %p ...\n", addr1); fflush(stdout);
    171         munmap(addr1, size);
    172     }
    173 
    174     printf("Done\n"); fflush(stdout);
    175     return 0;
    176 }
    177 
    178 int stack_smasher_test(int, char**) {
    179     int dummy = 0;
    180     printf("corrupting our stack...\n");
    181     *(volatile long long*)&dummy = 0;
    182     return 0;
    183 }
    184 
    185 // --------------------------------------------------------------------
    186 
    187 extern "C" void thumb_function_1(int*p);
    188 extern "C" void thumb_function_2(int*p);
    189 extern "C" void arm_function_3(int*p);
    190 extern "C" void arm_function_2(int*p);
    191 extern "C" void arm_function_1(int*p);
    192 
    193 void arm_function_3(int*) {
    194     int a = 0;
    195     thumb_function_2(&a);
    196 }
    197 
    198 void arm_function_2(int*) {
    199     int a = 0;
    200     thumb_function_1(&a);
    201 }
    202 
    203 void arm_function_1(int*) {
    204     int a = 0;
    205     arm_function_2(&a);
    206 }
    207 
    208 int crawl_test(int, char**) {
    209     int a = 0;
    210     arm_function_1(&a);
    211     return 0;
    212 }
    213