1*1366c37eSMatthew Wilcox #include <stdio.h> 2*1366c37eSMatthew Wilcox #include <stdlib.h> 3*1366c37eSMatthew Wilcox #include <unistd.h> 4*1366c37eSMatthew Wilcox #include <time.h> 5*1366c37eSMatthew Wilcox #include <assert.h> 6*1366c37eSMatthew Wilcox 7*1366c37eSMatthew Wilcox #include <linux/slab.h> 8*1366c37eSMatthew Wilcox #include <linux/radix-tree.h> 9*1366c37eSMatthew Wilcox 10*1366c37eSMatthew Wilcox #include "test.h" 11*1366c37eSMatthew Wilcox #include "regression.h" 12*1366c37eSMatthew Wilcox 13*1366c37eSMatthew Wilcox void __gang_check(unsigned long middle, long down, long up, int chunk, int hop) 14*1366c37eSMatthew Wilcox { 15*1366c37eSMatthew Wilcox long idx; 16*1366c37eSMatthew Wilcox RADIX_TREE(tree, GFP_KERNEL); 17*1366c37eSMatthew Wilcox 18*1366c37eSMatthew Wilcox middle = 1 << 30; 19*1366c37eSMatthew Wilcox 20*1366c37eSMatthew Wilcox for (idx = -down; idx < up; idx++) 21*1366c37eSMatthew Wilcox item_insert(&tree, middle + idx); 22*1366c37eSMatthew Wilcox 23*1366c37eSMatthew Wilcox item_check_absent(&tree, middle - down - 1); 24*1366c37eSMatthew Wilcox for (idx = -down; idx < up; idx++) 25*1366c37eSMatthew Wilcox item_check_present(&tree, middle + idx); 26*1366c37eSMatthew Wilcox item_check_absent(&tree, middle + up); 27*1366c37eSMatthew Wilcox 28*1366c37eSMatthew Wilcox item_gang_check_present(&tree, middle - down, 29*1366c37eSMatthew Wilcox up + down, chunk, hop); 30*1366c37eSMatthew Wilcox item_full_scan(&tree, middle - down, down + up, chunk); 31*1366c37eSMatthew Wilcox item_kill_tree(&tree); 32*1366c37eSMatthew Wilcox } 33*1366c37eSMatthew Wilcox 34*1366c37eSMatthew Wilcox void gang_check(void) 35*1366c37eSMatthew Wilcox { 36*1366c37eSMatthew Wilcox __gang_check(1 << 30, 128, 128, 35, 2); 37*1366c37eSMatthew Wilcox __gang_check(1 << 31, 128, 128, 32, 32); 38*1366c37eSMatthew Wilcox __gang_check(1 << 31, 128, 128, 32, 100); 39*1366c37eSMatthew Wilcox __gang_check(1 << 31, 128, 128, 17, 7); 40*1366c37eSMatthew Wilcox __gang_check(0xffff0000, 0, 65536, 17, 7); 41*1366c37eSMatthew Wilcox __gang_check(0xfffffffe, 1, 1, 17, 7); 42*1366c37eSMatthew Wilcox } 43*1366c37eSMatthew Wilcox 44*1366c37eSMatthew Wilcox void __big_gang_check(void) 45*1366c37eSMatthew Wilcox { 46*1366c37eSMatthew Wilcox unsigned long start; 47*1366c37eSMatthew Wilcox int wrapped = 0; 48*1366c37eSMatthew Wilcox 49*1366c37eSMatthew Wilcox start = 0; 50*1366c37eSMatthew Wilcox do { 51*1366c37eSMatthew Wilcox unsigned long old_start; 52*1366c37eSMatthew Wilcox 53*1366c37eSMatthew Wilcox // printf("0x%08lx\n", start); 54*1366c37eSMatthew Wilcox __gang_check(start, rand() % 113 + 1, rand() % 71, 55*1366c37eSMatthew Wilcox rand() % 157, rand() % 91 + 1); 56*1366c37eSMatthew Wilcox old_start = start; 57*1366c37eSMatthew Wilcox start += rand() % 1000000; 58*1366c37eSMatthew Wilcox start %= 1ULL << 33; 59*1366c37eSMatthew Wilcox if (start < old_start) 60*1366c37eSMatthew Wilcox wrapped = 1; 61*1366c37eSMatthew Wilcox } while (!wrapped); 62*1366c37eSMatthew Wilcox } 63*1366c37eSMatthew Wilcox 64*1366c37eSMatthew Wilcox void big_gang_check(void) 65*1366c37eSMatthew Wilcox { 66*1366c37eSMatthew Wilcox int i; 67*1366c37eSMatthew Wilcox 68*1366c37eSMatthew Wilcox for (i = 0; i < 1000; i++) { 69*1366c37eSMatthew Wilcox __big_gang_check(); 70*1366c37eSMatthew Wilcox srand(time(0)); 71*1366c37eSMatthew Wilcox printf("%d ", i); 72*1366c37eSMatthew Wilcox fflush(stdout); 73*1366c37eSMatthew Wilcox } 74*1366c37eSMatthew Wilcox } 75*1366c37eSMatthew Wilcox 76*1366c37eSMatthew Wilcox void add_and_check(void) 77*1366c37eSMatthew Wilcox { 78*1366c37eSMatthew Wilcox RADIX_TREE(tree, GFP_KERNEL); 79*1366c37eSMatthew Wilcox 80*1366c37eSMatthew Wilcox item_insert(&tree, 44); 81*1366c37eSMatthew Wilcox item_check_present(&tree, 44); 82*1366c37eSMatthew Wilcox item_check_absent(&tree, 43); 83*1366c37eSMatthew Wilcox item_kill_tree(&tree); 84*1366c37eSMatthew Wilcox } 85*1366c37eSMatthew Wilcox 86*1366c37eSMatthew Wilcox void dynamic_height_check(void) 87*1366c37eSMatthew Wilcox { 88*1366c37eSMatthew Wilcox int i; 89*1366c37eSMatthew Wilcox RADIX_TREE(tree, GFP_KERNEL); 90*1366c37eSMatthew Wilcox tree_verify_min_height(&tree, 0); 91*1366c37eSMatthew Wilcox 92*1366c37eSMatthew Wilcox item_insert(&tree, 42); 93*1366c37eSMatthew Wilcox tree_verify_min_height(&tree, 42); 94*1366c37eSMatthew Wilcox 95*1366c37eSMatthew Wilcox item_insert(&tree, 1000000); 96*1366c37eSMatthew Wilcox tree_verify_min_height(&tree, 1000000); 97*1366c37eSMatthew Wilcox 98*1366c37eSMatthew Wilcox assert(item_delete(&tree, 1000000)); 99*1366c37eSMatthew Wilcox tree_verify_min_height(&tree, 42); 100*1366c37eSMatthew Wilcox 101*1366c37eSMatthew Wilcox assert(item_delete(&tree, 42)); 102*1366c37eSMatthew Wilcox tree_verify_min_height(&tree, 0); 103*1366c37eSMatthew Wilcox 104*1366c37eSMatthew Wilcox for (i = 0; i < 1000; i++) { 105*1366c37eSMatthew Wilcox item_insert(&tree, i); 106*1366c37eSMatthew Wilcox tree_verify_min_height(&tree, i); 107*1366c37eSMatthew Wilcox } 108*1366c37eSMatthew Wilcox 109*1366c37eSMatthew Wilcox i--; 110*1366c37eSMatthew Wilcox for (;;) { 111*1366c37eSMatthew Wilcox assert(item_delete(&tree, i)); 112*1366c37eSMatthew Wilcox if (i == 0) { 113*1366c37eSMatthew Wilcox tree_verify_min_height(&tree, 0); 114*1366c37eSMatthew Wilcox break; 115*1366c37eSMatthew Wilcox } 116*1366c37eSMatthew Wilcox i--; 117*1366c37eSMatthew Wilcox tree_verify_min_height(&tree, i); 118*1366c37eSMatthew Wilcox } 119*1366c37eSMatthew Wilcox 120*1366c37eSMatthew Wilcox item_kill_tree(&tree); 121*1366c37eSMatthew Wilcox } 122*1366c37eSMatthew Wilcox 123*1366c37eSMatthew Wilcox void check_copied_tags(struct radix_tree_root *tree, unsigned long start, unsigned long end, unsigned long *idx, int count, int fromtag, int totag) 124*1366c37eSMatthew Wilcox { 125*1366c37eSMatthew Wilcox int i; 126*1366c37eSMatthew Wilcox 127*1366c37eSMatthew Wilcox for (i = 0; i < count; i++) { 128*1366c37eSMatthew Wilcox /* if (i % 1000 == 0) 129*1366c37eSMatthew Wilcox putchar('.'); */ 130*1366c37eSMatthew Wilcox if (idx[i] < start || idx[i] > end) { 131*1366c37eSMatthew Wilcox if (item_tag_get(tree, idx[i], totag)) { 132*1366c37eSMatthew Wilcox printf("%lu-%lu: %lu, tags %d-%d\n", start, end, idx[i], item_tag_get(tree, idx[i], fromtag), item_tag_get(tree, idx[i], totag)); 133*1366c37eSMatthew Wilcox } 134*1366c37eSMatthew Wilcox assert(!item_tag_get(tree, idx[i], totag)); 135*1366c37eSMatthew Wilcox continue; 136*1366c37eSMatthew Wilcox } 137*1366c37eSMatthew Wilcox if (item_tag_get(tree, idx[i], fromtag) ^ 138*1366c37eSMatthew Wilcox item_tag_get(tree, idx[i], totag)) { 139*1366c37eSMatthew Wilcox printf("%lu-%lu: %lu, tags %d-%d\n", start, end, idx[i], item_tag_get(tree, idx[i], fromtag), item_tag_get(tree, idx[i], totag)); 140*1366c37eSMatthew Wilcox } 141*1366c37eSMatthew Wilcox assert(!(item_tag_get(tree, idx[i], fromtag) ^ 142*1366c37eSMatthew Wilcox item_tag_get(tree, idx[i], totag))); 143*1366c37eSMatthew Wilcox } 144*1366c37eSMatthew Wilcox } 145*1366c37eSMatthew Wilcox 146*1366c37eSMatthew Wilcox #define ITEMS 50000 147*1366c37eSMatthew Wilcox 148*1366c37eSMatthew Wilcox void copy_tag_check(void) 149*1366c37eSMatthew Wilcox { 150*1366c37eSMatthew Wilcox RADIX_TREE(tree, GFP_KERNEL); 151*1366c37eSMatthew Wilcox unsigned long idx[ITEMS]; 152*1366c37eSMatthew Wilcox unsigned long start, end, count = 0, tagged, cur, tmp; 153*1366c37eSMatthew Wilcox int i; 154*1366c37eSMatthew Wilcox 155*1366c37eSMatthew Wilcox // printf("generating radix tree indices...\n"); 156*1366c37eSMatthew Wilcox start = rand(); 157*1366c37eSMatthew Wilcox end = rand(); 158*1366c37eSMatthew Wilcox if (start > end && (rand() % 10)) { 159*1366c37eSMatthew Wilcox cur = start; 160*1366c37eSMatthew Wilcox start = end; 161*1366c37eSMatthew Wilcox end = cur; 162*1366c37eSMatthew Wilcox } 163*1366c37eSMatthew Wilcox /* Specifically create items around the start and the end of the range 164*1366c37eSMatthew Wilcox * with high probability to check for off by one errors */ 165*1366c37eSMatthew Wilcox cur = rand(); 166*1366c37eSMatthew Wilcox if (cur & 1) { 167*1366c37eSMatthew Wilcox item_insert(&tree, start); 168*1366c37eSMatthew Wilcox if (cur & 2) { 169*1366c37eSMatthew Wilcox if (start <= end) 170*1366c37eSMatthew Wilcox count++; 171*1366c37eSMatthew Wilcox item_tag_set(&tree, start, 0); 172*1366c37eSMatthew Wilcox } 173*1366c37eSMatthew Wilcox } 174*1366c37eSMatthew Wilcox if (cur & 4) { 175*1366c37eSMatthew Wilcox item_insert(&tree, start-1); 176*1366c37eSMatthew Wilcox if (cur & 8) 177*1366c37eSMatthew Wilcox item_tag_set(&tree, start-1, 0); 178*1366c37eSMatthew Wilcox } 179*1366c37eSMatthew Wilcox if (cur & 16) { 180*1366c37eSMatthew Wilcox item_insert(&tree, end); 181*1366c37eSMatthew Wilcox if (cur & 32) { 182*1366c37eSMatthew Wilcox if (start <= end) 183*1366c37eSMatthew Wilcox count++; 184*1366c37eSMatthew Wilcox item_tag_set(&tree, end, 0); 185*1366c37eSMatthew Wilcox } 186*1366c37eSMatthew Wilcox } 187*1366c37eSMatthew Wilcox if (cur & 64) { 188*1366c37eSMatthew Wilcox item_insert(&tree, end+1); 189*1366c37eSMatthew Wilcox if (cur & 128) 190*1366c37eSMatthew Wilcox item_tag_set(&tree, end+1, 0); 191*1366c37eSMatthew Wilcox } 192*1366c37eSMatthew Wilcox 193*1366c37eSMatthew Wilcox for (i = 0; i < ITEMS; i++) { 194*1366c37eSMatthew Wilcox do { 195*1366c37eSMatthew Wilcox idx[i] = rand(); 196*1366c37eSMatthew Wilcox } while (item_lookup(&tree, idx[i])); 197*1366c37eSMatthew Wilcox 198*1366c37eSMatthew Wilcox item_insert(&tree, idx[i]); 199*1366c37eSMatthew Wilcox if (rand() & 1) { 200*1366c37eSMatthew Wilcox item_tag_set(&tree, idx[i], 0); 201*1366c37eSMatthew Wilcox if (idx[i] >= start && idx[i] <= end) 202*1366c37eSMatthew Wilcox count++; 203*1366c37eSMatthew Wilcox } 204*1366c37eSMatthew Wilcox /* if (i % 1000 == 0) 205*1366c37eSMatthew Wilcox putchar('.'); */ 206*1366c37eSMatthew Wilcox } 207*1366c37eSMatthew Wilcox 208*1366c37eSMatthew Wilcox // printf("\ncopying tags...\n"); 209*1366c37eSMatthew Wilcox cur = start; 210*1366c37eSMatthew Wilcox tagged = radix_tree_range_tag_if_tagged(&tree, &cur, end, ITEMS, 0, 1); 211*1366c37eSMatthew Wilcox 212*1366c37eSMatthew Wilcox // printf("checking copied tags\n"); 213*1366c37eSMatthew Wilcox assert(tagged == count); 214*1366c37eSMatthew Wilcox check_copied_tags(&tree, start, end, idx, ITEMS, 0, 1); 215*1366c37eSMatthew Wilcox 216*1366c37eSMatthew Wilcox /* Copy tags in several rounds */ 217*1366c37eSMatthew Wilcox // printf("\ncopying tags...\n"); 218*1366c37eSMatthew Wilcox cur = start; 219*1366c37eSMatthew Wilcox do { 220*1366c37eSMatthew Wilcox tmp = rand() % (count/10+2); 221*1366c37eSMatthew Wilcox tagged = radix_tree_range_tag_if_tagged(&tree, &cur, end, tmp, 0, 2); 222*1366c37eSMatthew Wilcox } while (tmp == tagged); 223*1366c37eSMatthew Wilcox 224*1366c37eSMatthew Wilcox // printf("%lu %lu %lu\n", tagged, tmp, count); 225*1366c37eSMatthew Wilcox // printf("checking copied tags\n"); 226*1366c37eSMatthew Wilcox check_copied_tags(&tree, start, end, idx, ITEMS, 0, 2); 227*1366c37eSMatthew Wilcox assert(tagged < tmp); 228*1366c37eSMatthew Wilcox verify_tag_consistency(&tree, 0); 229*1366c37eSMatthew Wilcox verify_tag_consistency(&tree, 1); 230*1366c37eSMatthew Wilcox verify_tag_consistency(&tree, 2); 231*1366c37eSMatthew Wilcox // printf("\n"); 232*1366c37eSMatthew Wilcox item_kill_tree(&tree); 233*1366c37eSMatthew Wilcox } 234*1366c37eSMatthew Wilcox 235*1366c37eSMatthew Wilcox static void single_thread_tests(void) 236*1366c37eSMatthew Wilcox { 237*1366c37eSMatthew Wilcox int i; 238*1366c37eSMatthew Wilcox 239*1366c37eSMatthew Wilcox tag_check(); 240*1366c37eSMatthew Wilcox printf("after tag_check: %d allocated\n", nr_allocated); 241*1366c37eSMatthew Wilcox gang_check(); 242*1366c37eSMatthew Wilcox printf("after gang_check: %d allocated\n", nr_allocated); 243*1366c37eSMatthew Wilcox add_and_check(); 244*1366c37eSMatthew Wilcox printf("after add_and_check: %d allocated\n", nr_allocated); 245*1366c37eSMatthew Wilcox dynamic_height_check(); 246*1366c37eSMatthew Wilcox printf("after dynamic_height_check: %d allocated\n", nr_allocated); 247*1366c37eSMatthew Wilcox big_gang_check(); 248*1366c37eSMatthew Wilcox printf("after big_gang_check: %d allocated\n", nr_allocated); 249*1366c37eSMatthew Wilcox for (i = 0; i < 2000; i++) { 250*1366c37eSMatthew Wilcox copy_tag_check(); 251*1366c37eSMatthew Wilcox printf("%d ", i); 252*1366c37eSMatthew Wilcox fflush(stdout); 253*1366c37eSMatthew Wilcox } 254*1366c37eSMatthew Wilcox printf("after copy_tag_check: %d allocated\n", nr_allocated); 255*1366c37eSMatthew Wilcox } 256*1366c37eSMatthew Wilcox 257*1366c37eSMatthew Wilcox int main(void) 258*1366c37eSMatthew Wilcox { 259*1366c37eSMatthew Wilcox rcu_register_thread(); 260*1366c37eSMatthew Wilcox radix_tree_init(); 261*1366c37eSMatthew Wilcox 262*1366c37eSMatthew Wilcox regression1_test(); 263*1366c37eSMatthew Wilcox regression2_test(); 264*1366c37eSMatthew Wilcox single_thread_tests(); 265*1366c37eSMatthew Wilcox 266*1366c37eSMatthew Wilcox sleep(1); 267*1366c37eSMatthew Wilcox printf("after sleep(1): %d allocated\n", nr_allocated); 268*1366c37eSMatthew Wilcox rcu_unregister_thread(); 269*1366c37eSMatthew Wilcox 270*1366c37eSMatthew Wilcox exit(0); 271*1366c37eSMatthew Wilcox } 272