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