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