1#include "perf_index.h" 2#include "fail.h" 3#include <stdlib.h> 4#include <unistd.h> 5#include <string.h> 6#include <sys/sysctl.h> 7 8static char *memblock; 9static size_t memsize; 10 11size_t hw_memsize(void) { 12 int mib[2]; 13 size_t len; 14 size_t my_memsize; 15 int retval; 16 17 mib[0] = CTL_HW; 18 mib[1] = HW_MEMSIZE; 19 len = sizeof(my_memsize); 20 21 retval = sysctl(mib, 2, &my_memsize, &len, NULL, 0); 22 23 if(retval != 0) 24 return 0; 25 26 return my_memsize; 27} 28 29DECL_SETUP { 30 char *memblockfiller; 31 long long i; 32 int pgsz = getpagesize(); 33 34 /* Heuristic: use half the physical memory, hopefully this should work on all 35 * devices. We use the amount of physical memory, rather than some softer 36 * metric, like amount of free memory, so that the memory allocated is always 37 * consistent for a given device. 38 */ 39 memsize = hw_memsize(); 40 VERIFY(memsize > 0, "hw_memsize failed"); 41 memsize = memsize/2; 42 43 memblock = (char*)malloc(memsize); 44 VERIFY(memblock != NULL, "malloc failed"); 45 46 memblockfiller = memblock; 47 48 /* Do this manually, to make sure everything is paged in */ 49 for(i=0; i<memsize; i+=pgsz) { 50 memblockfiller[i] = 1; 51 } 52 53 return PERFINDEX_SUCCESS; 54} 55 56/* figures out what region of memory to copy, so it does interfere with other 57threads, */ 58DECL_TEST { 59 long long left = length; 60 long long region_len = memsize / num_threads / 2; 61 long long region_start = memsize / num_threads * thread_id / 2; 62 long long copy_len; 63 64 if(thread_id < memsize / 2 % num_threads) { 65 region_start += thread_id; 66 region_len++; 67 } 68 else { 69 region_start += memsize / 2 % num_threads; 70 } 71 72 while(left>0) { 73 copy_len = region_len < left ? region_len : left; 74 memcpy(memblock+region_start+memsize/2, memblock+region_start, copy_len); 75 left -= copy_len; 76 } 77 78 return PERFINDEX_SUCCESS; 79} 80 81DECL_CLEANUP { 82 free(memblock); 83 return PERFINDEX_SUCCESS; 84} 85