int main(int argc, char *argv[]) { UINT i; unsigned int N; UINT NSTATES; unsigned int rule; CA *ca; char *graph; if (argc != 3) { fprintf(stderr, "usage: %s rule ca-size\n", PROGRAM_NAME); exit(EXIT_FAILURE); } sscanf(argv[1], "%u", &rule); sscanf(argv[2], "%u", &N); if (DEBUG) fprintf(stderr, "rule %u\nN=%u\n", rule, N); ca = ca_create(N, rule); NSTATES = 2; NSTATES <<= (N - 1); graph = create_graph(NSTATES); for (i = 0; i < NSTATES; ++i) flags_unset(graph, i, STATE_ALL_SET_MASK); for (i = 0; i < NSTATES; ++i) if (!flags_test(graph, i, STATE_HAS_BEEN_VISITED)) search_cycle(ca, graph, i); free_graph(graph); ca_destroy(ca); return EXIT_SUCCESS; }
/** Check ordering of one lock */ static void check_order_lock(struct order_lock* lock) { struct lock_ref start; if(lock->visited) return; start.node.key = &lock->id; start.lock = lock; start.file = lock->create_file; start.line = lock->create_line; if(!lock->create_file) log_err("lock %u %u does not have create info", (unsigned)lock->id.thr, (unsigned)lock->id.instance); /* depth first search to find cycle with this lock at head */ lock->dfs_next = NULL; search_cycle(&start, 0, &start); }
/** recursive function to depth first search for cycles. * @param visit: the lock visited at this step. * its dfs_next pointer gives the visited lock up in recursion. * same as lookfor at level 0. * @param level: depth of recursion. 0 is start. * @param from: search for matches from unvisited node upwards. */ static void search_cycle(struct lock_ref* visit, int level, struct lock_ref* from) { struct lock_ref* ref; /* check for cycle */ if(detect_cycle(visit, from) && level != 0) { found_cycle(visit, level); fatal_exit("found lock order cycle"); } /* recurse */ if(!visit->lock->visited) from = visit; if(verb > 1) fprintf(stderr, "[%d] visit lock %u %u %s %d\n", level, (unsigned)visit->lock->id.thr, (unsigned)visit->lock->id.instance, visit->lock->create_file, visit->lock->create_line); RBTREE_FOR(ref, struct lock_ref*, visit->lock->smaller) { ref->lock->dfs_next = visit; search_cycle(ref, level+1, from); } visit->lock->visited = 1; }