memtest.cpp revision 1348ce27ee9bb8e50a3294879c1523fa4b4d8f8b
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 31nsecs_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 39static 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 " per_core_bandwidth [--size BYTES]\n" 45 " --type copy_ldrd_strd | copy_ldmia_stmia | copy_vld_vst |\n" 46 " copy_vldmia_vstmia | memcpy | write_strd | write_stmia |\n" 47 " write_vst | write_vstmia | memset\n" 48 " multithread_bandwidth [--size BYTES]\n" 49 " --type copy_ldrd_strd | copy_ldmia_stmia | copy_vld_vst |\n" 50 " copy_vldmia_vstmia | memcpy | write_strd | write_stmia |\n" 51 " write_vst | write_vstmia | memset\n" 52 " --num_threads NUM_THREADS_TO_RUN\n" 53 " malloc [fill]\n" 54 " madvise\n" 55 " resampler\n" 56 " crash\n" 57 " stack (stack smasher)\n" 58 " crawl\n" 59 , p); 60} 61 62int copy_bandwidth(int argc, char** argv); 63int write_bandwidth(int argc, char** argv); 64int per_core_bandwidth(int argc, char** argv); 65int multithread_bandwidth(int argc, char** argv); 66int malloc_test(int argc, char** argv); 67int madvise_test(int argc, char** argv); 68int crash_test(int argc, char** argv); 69int stack_smasher_test(int argc, char** argv); 70int crawl_test(int argc, char** argv); 71int fp_test(int argc, char** argv); 72 73typedef struct { 74 const char *cmd_name; 75 int (*func)(int argc, char** argv); 76} function_t; 77 78function_t function_table[] = { 79 { "malloc", malloc_test }, 80 { "madvise", madvise_test }, 81 { "crash", crash_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 { "per_core_bandwidth", per_core_bandwidth }, 88 { "multithread_bandwidth", multithread_bandwidth }, 89}; 90 91int main(int argc, char** argv) 92{ 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 110int malloc_test(int argc, char** argv) 111{ 112 bool fill = (argc>=2 && !strcmp(argv[1], "fill")); 113 size_t total = 0; 114 size_t size = 0x40000000; 115 while (size) { 116 void* addr = malloc(size); 117 if (addr == 0) { 118 printf("size = %9zd failed\n", size); 119 size >>= 1; 120 } else { 121 total += size; 122 printf("size = %9zd, addr = %p (total = %9zd (%zd MB))\n", 123 size, addr, total, total / (1024*1024)); 124 if (fill) { 125 printf("filling...\n"); 126 fflush(stdout); 127 memset(addr, 0, size); 128 } 129 size = size + (size>>1); 130 } 131 } 132 printf("done. allocated %zd MB\n", total / (1024*1024)); 133 return 0; 134} 135 136int madvise_test(int argc, char** argv) 137{ 138 for (int i=0 ; i<2 ; i++) { 139 size_t size = i==0 ? 4096 : 48*1024*1024; // 48 MB 140 printf("Allocating %zd MB... ", size/(1024*1024)); fflush(stdout); 141 void* addr1 = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 142 printf("%p (%s)\n", addr1, addr1==(void*)-1 ? "failed" : "OK"); fflush(stdout); 143 144 printf("touching %p...\n", addr1); fflush(stdout); 145 memset(addr1, 0x55, size); 146 147 printf("advising DONTNEED...\n"); fflush(stdout); 148 madvise(addr1, size, MADV_DONTNEED); 149 150 printf("reading back %p...\n", addr1); fflush(stdout); 151 if (*(long*)addr1 == 0) { 152 printf("madvise freed some pages\n"); 153 } else if (*(long*)addr1 == 0x55555555) { 154 printf("pages are still there\n"); 155 } else { 156 printf("getting garbage back\n"); 157 } 158 159 printf("Allocating %zd MB... ", size/(1024*1024)); fflush(stdout); 160 void* addr2 = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 161 printf("%p (%s)\n", addr2, addr2==(void*)-1 ? "failed" : "OK"); fflush(stdout); 162 163 printf("touching %p...\n", addr2); fflush(stdout); 164 memset(addr2, 0xAA, size); 165 166 printf("unmap %p ...\n", addr2); fflush(stdout); 167 munmap(addr2, size); 168 169 printf("touching %p...\n", addr1); fflush(stdout); 170 memset(addr1, 0x55, size); 171 172 printf("unmap %p ...\n", addr1); fflush(stdout); 173 munmap(addr1, size); 174 } 175 176 printf("Done\n"); fflush(stdout); 177 return 0; 178} 179 180int crash_test(int argc, char** argv) 181{ 182 printf("about to crash...\n"); 183 asm volatile( 184 "mov r0, #0 \n" 185 "mov r1, #1 \n" 186 "mov r2, #2 \n" 187 "mov r3, #3 \n" 188 "ldr r12, [r0] \n" 189 ); 190 191 return 0; 192} 193 194int stack_smasher_test(int argc, char** argv) 195{ 196 int dummy = 0; 197 printf("corrupting our stack...\n"); 198 *(volatile long long*)&dummy = 0; 199 return 0; 200} 201 202// -------------------------------------------------------------------- 203 204extern "C" void thumb_function_1(int*p); 205extern "C" void thumb_function_2(int*p); 206extern "C" void arm_function_3(int*p); 207extern "C" void arm_function_2(int*p); 208extern "C" void arm_function_1(int*p); 209 210void arm_function_3(int*p) { 211 int a = 0; 212 thumb_function_2(&a); 213} 214 215void arm_function_2(int*p) { 216 int a = 0; 217 thumb_function_1(&a); 218} 219 220void arm_function_1(int*p) { 221 int a = 0; 222 arm_function_2(&a); 223} 224 225int crawl_test(int argc, char** argv) 226{ 227 int a = 0; 228 arm_function_1(&a); 229 return 0; 230} 231 232