1 /** @brief Unit-test for DRD's bitmap implementation. */ 2 3 4 #include <assert.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <unistd.h> 9 10 #include "coregrind/m_xarray.c" 11 #include "coregrind/m_poolalloc.c" 12 #include "coregrind/m_oset.c" 13 #include "drd/drd_bitmap.c" 14 #include "drd/pub_drd_bitmap.h" 15 16 17 #ifndef MIN 18 #define MIN(x, y) ((x) < (y) ? (x) : (y)) 19 #endif 20 #ifndef MAX 21 #define MAX(x, y) ((x) > (y) ? (x) : (y)) 22 #endif 23 24 25 /* Replacements for Valgrind core functionality. */ 26 27 void* VG_(malloc)(const HChar* cc, SizeT nbytes) 28 { return malloc(nbytes); } 29 void VG_(free)(void* p) 30 { return free(p); } 31 void VG_(assert_fail)(Bool isCore, const HChar* assertion, const HChar* file, 32 Int line, const HChar* function, const HChar* format, 33 ...) 34 { 35 fprintf(stderr, 36 "%s:%u: %s%sAssertion `%s' failed.\n", 37 file, 38 line, 39 function ? (char*)function : "", 40 function ? ": " : "", 41 assertion); 42 fflush(stdout); 43 fflush(stderr); 44 abort(); 45 } 46 47 Int VG_(strcmp)( const HChar* s1, const HChar* s2 ) 48 { return strcmp(s1, s2); } 49 void* VG_(memset)(void *s, Int c, SizeT sz) 50 { return memset(s, c, sz); } 51 void* VG_(memcpy)(void *d, const void *s, SizeT sz) 52 { return memcpy(d, s, sz); } 53 void* VG_(memmove)(void *d, const void *s, SizeT sz) 54 { return memmove(d, s, sz); } 55 Int VG_(memcmp)(const void* s1, const void* s2, SizeT n) 56 { return memcmp(s1, s2, n); } 57 UInt VG_(printf)(const HChar *format, ...) 58 { UInt ret; va_list vargs; va_start(vargs, format); ret = vprintf(format, vargs); va_end(vargs); return ret; } 59 UInt VG_(message)(VgMsgKind kind, const HChar* format, ...) 60 { UInt ret; va_list vargs; va_start(vargs, format); ret = vprintf(format, vargs); va_end(vargs); printf("\n"); return ret; } 61 Bool DRD_(is_suppressed)(const Addr a1, const Addr a2) 62 { assert(0); } 63 void VG_(vcbprintf)(void(*char_sink)(HChar, void* opaque), 64 void* opaque, 65 const HChar* format, va_list vargs) 66 { assert(0); } 67 void VG_(ssort)( void* base, SizeT nmemb, SizeT size, 68 Int (*compar)(const void*, const void*) ) 69 { assert(0); } 70 71 /* Actual unit test */ 72 73 static int s_verbose = 1; 74 75 static 76 struct { Addr address; SizeT size; BmAccessTypeT access_type; } 77 s_test1_args[] = { 78 { 0, 0, eLoad }, 79 { 0, 1, eLoad }, 80 { 666, 4, eLoad }, 81 { 667, 2, eStore }, 82 { 1024, 1, eStore }, 83 { 0xffffULL, 1, eStore }, 84 { 0x0001ffffULL, 1, eLoad }, 85 { 0x00ffffffULL, 1, eLoad }, 86 { 0xffffffffULL - (((1 << ADDR_LSB_BITS) + 1) << ADDR_IGNORED_BITS), 87 1, eStore }, 88 #if defined(VGP_amd64_linux) || defined(VGP_ppc64be_linux) \ 89 || defined(VGP_ppc64le_linux) 90 { 0xffffffffULL - (1 << ADDR_LSB_BITS << ADDR_IGNORED_BITS), 91 1, eStore }, 92 { 0xffffffffULL, 1, eStore }, 93 { 0x100000000ULL, 1, eStore }, 94 { -2ULL - (1 << ADDR_LSB_BITS << ADDR_IGNORED_BITS), 95 1, eStore }, 96 #endif 97 }; 98 99 /** 100 * Compare two bitmaps and if different, print the differences. 101 */ 102 int bm_equal_print_diffs(struct bitmap* bm1, struct bitmap* bm2) 103 { 104 int equal; 105 106 equal = DRD_(bm_equal)(bm1, bm2); 107 if (s_verbose && ! equal) 108 { 109 unsigned i; 110 111 VG_(printf)("Bitmaps are different.\n"); 112 for (i = 0; i < 0x10000; i++) 113 { 114 if (DRD_(bm_has_1)(bm1, i, eLoad) != DRD_(bm_has_1)(bm2, i, eLoad) 115 || DRD_(bm_has_1)(bm1, i, eStore) != DRD_(bm_has_1)(bm2, i, eStore)) 116 { 117 printf("0x%x %c %c %c %c\n", 118 i, 119 DRD_(bm_has_1)(bm1, i, eLoad) ? 'R' : ' ', 120 DRD_(bm_has_1)(bm1, i, eStore) ? 'W' : ' ', 121 DRD_(bm_has_1)(bm2, i, eLoad) ? 'R' : ' ', 122 DRD_(bm_has_1)(bm2, i, eStore) ? 'W' : ' ' 123 ); 124 } 125 } 126 fflush(stdout); 127 } 128 129 return equal; 130 } 131 132 void bm_test1(void) 133 { 134 struct bitmap* bm; 135 struct bitmap* bm2; 136 unsigned i, j; 137 138 bm = DRD_(bm_new)(); 139 140 for (i = 0; i < sizeof(s_test1_args)/sizeof(s_test1_args[0]); i++) 141 { 142 DRD_(bm_access_range)(bm, 143 s_test1_args[i].address, 144 s_test1_args[i].address + s_test1_args[i].size, 145 s_test1_args[i].access_type); 146 } 147 148 for (i = 0; i < sizeof(s_test1_args)/sizeof(s_test1_args[0]); i++) 149 { 150 for (j = 0; 151 first_address_with_higher_lsb(j) <= s_test1_args[i].size; 152 j = first_address_with_higher_lsb(j)) 153 { 154 tl_assert(DRD_(bm_has_1)(bm, 155 s_test1_args[i].address + j, 156 s_test1_args[i].access_type)); 157 } 158 } 159 160 bm2 = DRD_(bm_new)(); 161 DRD_(bm_merge2)(bm2, bm); 162 DRD_(bm_merge2)(bm2, bm); 163 assert(bm_equal_print_diffs(bm2, bm)); 164 165 if (s_verbose) 166 VG_(printf)("Deleting bitmap bm\n"); 167 DRD_(bm_delete)(bm); 168 if (s_verbose) 169 VG_(printf)("Deleting bitmap bm2\n"); 170 DRD_(bm_delete)(bm2); 171 } 172 173 /** Test whether bm_equal() works correctly. */ 174 void bm_test2() 175 { 176 struct bitmap* bm1; 177 struct bitmap* bm2; 178 179 bm1 = DRD_(bm_new)(); 180 bm2 = DRD_(bm_new)(); 181 DRD_(bm_access_load_1)(bm1, 7); 182 DRD_(bm_access_load_1)(bm2, make_address(1, 0) + 7); 183 assert(! DRD_(bm_equal)(bm1, bm2)); 184 assert(! DRD_(bm_equal)(bm2, bm1)); 185 DRD_(bm_access_load_1)(bm2, 7); 186 assert(! DRD_(bm_equal)(bm1, bm2)); 187 assert(! DRD_(bm_equal)(bm2, bm1)); 188 DRD_(bm_access_store_1)(bm1, make_address(1, 0) + 7); 189 assert(! DRD_(bm_equal)(bm1, bm2)); 190 assert(! DRD_(bm_equal)(bm2, bm1)); 191 DRD_(bm_delete)(bm2); 192 DRD_(bm_delete)(bm1); 193 } 194 195 /** Torture test of the functions that set or clear a range of bits. */ 196 void bm_test3(const int outer_loop_step, const int inner_loop_step) 197 { 198 unsigned i, j; 199 struct bitmap* bm1; 200 struct bitmap* bm2; 201 202 const Addr lb = make_address(2, 0) - 2 * BITS_PER_UWORD; 203 const Addr ub = make_address(2, 0) + 2 * BITS_PER_UWORD; 204 205 assert(outer_loop_step >= 1); 206 assert((outer_loop_step % ADDR_GRANULARITY) == 0); 207 assert(inner_loop_step >= 1); 208 assert((inner_loop_step % ADDR_GRANULARITY) == 0); 209 210 bm1 = DRD_(bm_new)(); 211 bm2 = DRD_(bm_new)(); 212 for (i = lb; i < ub; i += outer_loop_step) 213 { 214 for (j = i + ADDR_GRANULARITY; j < ub; j += inner_loop_step) 215 { 216 DRD_(bm_access_range_load)(bm1, i, j); 217 DRD_(bm_clear_load)(bm1, i, j); 218 assert(bm_equal_print_diffs(bm1, bm2)); 219 DRD_(bm_access_load_1)(bm1, i); 220 DRD_(bm_clear_load)(bm1, i, i + MAX(1, ADDR_GRANULARITY)); 221 assert(bm_equal_print_diffs(bm1, bm2)); 222 DRD_(bm_access_load_2)(bm1, i); 223 DRD_(bm_clear_load)(bm1, i, i + MAX(2, ADDR_GRANULARITY)); 224 assert(bm_equal_print_diffs(bm1, bm2)); 225 DRD_(bm_access_load_4)(bm1, i); 226 DRD_(bm_clear_load)(bm1, i, i + MAX(4, ADDR_GRANULARITY)); 227 assert(bm_equal_print_diffs(bm1, bm2)); 228 DRD_(bm_access_load_8)(bm1, i); 229 DRD_(bm_clear_load)(bm1, i, i + MAX(8, ADDR_GRANULARITY)); 230 assert(bm_equal_print_diffs(bm1, bm2)); 231 232 DRD_(bm_access_range_store)(bm1, i, j); 233 DRD_(bm_clear_store)(bm1, i, j); 234 assert(bm_equal_print_diffs(bm1, bm2)); 235 DRD_(bm_access_store_1)(bm1, i); 236 DRD_(bm_clear_store)(bm1, i, i + MAX(1, ADDR_GRANULARITY)); 237 assert(bm_equal_print_diffs(bm1, bm2)); 238 DRD_(bm_access_store_2)(bm1, i); 239 DRD_(bm_clear_store)(bm1, i, i + MAX(2, ADDR_GRANULARITY)); 240 assert(bm_equal_print_diffs(bm1, bm2)); 241 DRD_(bm_access_store_4)(bm1, i); 242 DRD_(bm_clear_store)(bm1, i, i + MAX(4, ADDR_GRANULARITY)); 243 assert(bm_equal_print_diffs(bm1, bm2)); 244 DRD_(bm_access_store_8)(bm1, i); 245 DRD_(bm_clear_store)(bm1, i, i + MAX(8, ADDR_GRANULARITY)); 246 assert(bm_equal_print_diffs(bm1, bm2)); 247 248 DRD_(bm_access_range_load)(bm1, i, j); 249 DRD_(bm_access_range_store)(bm1, i, j); 250 DRD_(bm_clear)(bm1, i, j); 251 assert(bm_equal_print_diffs(bm1, bm2)); 252 DRD_(bm_access_load_1)(bm1, i); 253 DRD_(bm_access_store_1)(bm1, i); 254 DRD_(bm_clear)(bm1, i, i + MAX(1, ADDR_GRANULARITY)); 255 assert(bm_equal_print_diffs(bm1, bm2)); 256 DRD_(bm_access_load_2)(bm1, i); 257 DRD_(bm_access_store_2)(bm1, i); 258 DRD_(bm_clear)(bm1, i, i + MAX(2, ADDR_GRANULARITY)); 259 assert(bm_equal_print_diffs(bm1, bm2)); 260 DRD_(bm_access_load_4)(bm1, i); 261 DRD_(bm_access_store_4)(bm1, i); 262 DRD_(bm_clear)(bm1, i, i + MAX(4, ADDR_GRANULARITY)); 263 assert(bm_equal_print_diffs(bm1, bm2)); 264 DRD_(bm_access_load_8)(bm1, i); 265 DRD_(bm_access_store_8)(bm1, i); 266 DRD_(bm_clear)(bm1, i, i + MAX(8, ADDR_GRANULARITY)); 267 assert(bm_equal_print_diffs(bm1, bm2)); 268 } 269 } 270 DRD_(bm_access_range_load)(bm1, 0, make_address(2, 0) + 2 * BITS_PER_UWORD); 271 DRD_(bm_access_range_store)(bm1, 0, make_address(2, 0) + 2 * BITS_PER_UWORD); 272 DRD_(bm_access_range_load)(bm2, 0, make_address(2, 0) + 2 * BITS_PER_UWORD); 273 DRD_(bm_access_range_store)(bm2, 0, make_address(2, 0) + 2 * BITS_PER_UWORD); 274 for (i = make_address(1, 0) - 2 * BITS_PER_UWORD; 275 i < make_address(1, 0) + 2 * BITS_PER_UWORD; 276 i += outer_loop_step) 277 { 278 for (j = i + 1; j < ub; j += inner_loop_step) 279 { 280 DRD_(bm_clear_load)(bm1, i, j); 281 DRD_(bm_access_range_load)(bm1, i, j); 282 assert(bm_equal_print_diffs(bm1, bm2)); 283 DRD_(bm_clear_load)(bm1, i, i+1); 284 DRD_(bm_access_load_1)(bm1, i); 285 assert(bm_equal_print_diffs(bm1, bm2)); 286 DRD_(bm_clear_load)(bm1, i, i+2); 287 DRD_(bm_access_load_2)(bm1, i); 288 assert(bm_equal_print_diffs(bm1, bm2)); 289 DRD_(bm_clear_load)(bm1, i, i+4); 290 DRD_(bm_access_load_4)(bm1, i); 291 assert(bm_equal_print_diffs(bm1, bm2)); 292 DRD_(bm_clear_load)(bm1, i, i+8); 293 DRD_(bm_access_load_8)(bm1, i); 294 assert(bm_equal_print_diffs(bm1, bm2)); 295 296 DRD_(bm_clear_store)(bm1, i, j); 297 DRD_(bm_access_range_store)(bm1, i, j); 298 assert(bm_equal_print_diffs(bm1, bm2)); 299 DRD_(bm_clear_store)(bm1, i, i+1); 300 DRD_(bm_access_store_1)(bm1, i); 301 assert(bm_equal_print_diffs(bm1, bm2)); 302 DRD_(bm_clear_store)(bm1, i, i+2); 303 DRD_(bm_access_store_2)(bm1, i); 304 assert(bm_equal_print_diffs(bm1, bm2)); 305 DRD_(bm_clear_store)(bm1, i, i+4); 306 DRD_(bm_access_store_4)(bm1, i); 307 assert(bm_equal_print_diffs(bm1, bm2)); 308 DRD_(bm_clear_store)(bm1, i, i+8); 309 DRD_(bm_access_store_8)(bm1, i); 310 assert(bm_equal_print_diffs(bm1, bm2)); 311 312 DRD_(bm_clear)(bm1, i, j); 313 DRD_(bm_access_range_load)(bm1, i, j); 314 DRD_(bm_access_range_store)(bm1, i, j); 315 assert(bm_equal_print_diffs(bm1, bm2)); 316 } 317 } 318 DRD_(bm_delete)(bm2); 319 DRD_(bm_delete)(bm1); 320 } 321 322 int main(int argc, char** argv) 323 { 324 int outer_loop_step = ADDR_GRANULARITY; 325 int inner_loop_step = ADDR_GRANULARITY; 326 int optchar; 327 328 while ((optchar = getopt(argc, argv, "s:t:q")) != EOF) 329 { 330 switch (optchar) 331 { 332 case 's': 333 outer_loop_step = atoi(optarg); 334 break; 335 case 't': 336 inner_loop_step = atoi(optarg); 337 break; 338 case 'q': 339 s_verbose = 0; 340 break; 341 default: 342 fprintf(stderr, 343 "Usage: %s [-s<outer_loop_step>] [-t<inner_loop_step>] [-q].\n", 344 argv[0]); 345 break; 346 } 347 } 348 349 fprintf(stderr, "Start of DRD BM unit test.\n"); 350 351 DRD_(bm_module_init)(); 352 bm_test1(); 353 bm_test2(); 354 bm_test3(outer_loop_step, inner_loop_step); 355 DRD_(bm_module_cleanup)(); 356 357 fprintf(stderr, "End of DRD BM unit test.\n"); 358 359 return 0; 360 } 361