/** * Open and lock the given file, ensuring that no deadlock will occur now or in the future over contention for this file. * If opening this file immediately would cause a deadlock, this method will block until the file can be safely opened and locked. * If the file cannot be opened, NULL is returned. * * Parameters: path - path to the file you wish to open and lock * mode - mode in which to open the file (same as the argument to fopen()) * Returns: A file pointer to the opened file or NULL on error */ FILE *sfs_fopen(char *path, char *mode) { mutex_lock(memory); // Turn claim edge to assignment edge node *resource = find_file_node(memory, path); node *process = find_process_node(memory, getpid()); if(resource == NULL || process == NULL) {\ mutex_unlock(memory); return NULL; } delete_out_edge(memory, process, resource); add_out_edge(memory, resource, process); // While a cycle exists while(cycle_exists(memory)) { // Convert back to claim edge delete_out_edge(memory, resource, process); add_out_edge(memory, process, resource); // Wait pthread_cond_wait(get_cycle_cond(memory), get_lock(memory)); // Add edge back delete_out_edge(memory, process, resource); add_out_edge(memory, resource, process); } // Upon getting the lock and assuring no cycle, open the file FILE *res = fopen(path, mode); resource->fp = res; mutex_unlock(memory); return res; }
static int cycle_exists(cdg_vertex_t * start, cdg_vertex_t * current, cdg_vertex_t * prev, int visit_num) { int i, new_visit_num; int cycle_found = 0; if (current != NULL && current->visiting_number > 0) { if (visit_num > current->visiting_number && current->seen == 0) { cycle_found = 1; } } else { if (current == NULL) { current = start; CL_ASSERT(prev == NULL); } current->visiting_number = visit_num; if (prev != NULL) { prev->next = current; CL_ASSERT(prev->to == current->from); CL_ASSERT(prev->visiting_number > 0); } new_visit_num = visit_num + 1; for (i = 0; i < current->num_deps; i++) { cycle_found = cycle_exists(start, current->deps[i].v, current, new_visit_num); if (cycle_found == 1) i = current->num_deps; } current->seen = 1; if (prev != NULL) prev->next = NULL; } return cycle_found; }
static int lash_core(lash_t * p_lash) { osm_log_t *p_log = &p_lash->p_osm->log; unsigned num_switches = p_lash->num_switches; switch_t **switches = p_lash->switches; unsigned lanes_needed = 1; unsigned int i, j, k, dest_switch = 0; reachable_dest_t *dests, *idest; int cycle_found = 0; unsigned v_lane; int stop = 0, output_link, i_next_switch; int output_link2, i_next_switch2; int cycle_found2 = 0; int status = -1; int *switch_bitmap = NULL; /* Bitmap to check if we have processed this pair */ unsigned start_vl = p_lash->p_osm->subn.opt.lash_start_vl; OSM_LOG_ENTER(p_log); if (p_lash->p_osm->subn.opt.do_mesh_analysis && osm_do_mesh_analysis(p_lash)) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D05: Mesh analysis failed\n"); goto Exit; } for (i = 0; i < num_switches; i++) { shortest_path(p_lash, i); if (generate_routing_func_for_mst(p_lash, i, &dests)) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D06: " "generate_routing_func_for_mst failed\n"); goto Exit; } idest = dests; while (idest != NULL) { dests = dests->next; free(idest); idest = dests; } for (j = 0; j < num_switches; j++) { switches[j]->used_channels = 0; switches[j]->q_state = UNQUEUED; } } switch_bitmap = calloc(num_switches * num_switches, sizeof(int)); if (!switch_bitmap) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D04: " "Failed allocating switch_bitmap - out of memory\n"); goto Exit; } for (i = 0; i < num_switches; i++) { for (dest_switch = 0; dest_switch < num_switches; dest_switch++) if (dest_switch != i && switch_bitmap[i * num_switches + dest_switch] == 0) { v_lane = 0; stop = 0; while (v_lane < lanes_needed && stop == 0) { if (generate_cdg_for_sp(p_lash, i, dest_switch, v_lane) || generate_cdg_for_sp(p_lash, dest_switch, i, v_lane)) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D07: generate_cdg_for_sp failed\n"); goto Exit; } output_link = switches[i]->routing_table[dest_switch].out_link; output_link2 = switches[dest_switch]->routing_table[i].out_link; i_next_switch = get_next_switch(p_lash, i, output_link); i_next_switch2 = get_next_switch(p_lash, dest_switch, output_link2); CL_ASSERT(p_lash-> cdg_vertex_matrix[v_lane][i][i_next_switch] != NULL); CL_ASSERT(p_lash-> cdg_vertex_matrix[v_lane][dest_switch] [i_next_switch2] != NULL); cycle_found = cycle_exists(p_lash-> cdg_vertex_matrix[v_lane][i] [i_next_switch], NULL, NULL, 1); cycle_found2 = cycle_exists(p_lash-> cdg_vertex_matrix[v_lane][dest_switch] [i_next_switch2], NULL, NULL, 1); for (j = 0; j < num_switches; j++) for (k = 0; k < num_switches; k++) if (p_lash-> cdg_vertex_matrix[v_lane][j][k] != NULL) { p_lash-> cdg_vertex_matrix[v_lane][j] [k]->visiting_number = 0; p_lash-> cdg_vertex_matrix[v_lane][j] [k]->seen = 0; } if (cycle_found == 1 || cycle_found2 == 1) { remove_temp_depend_for_sp(p_lash, i, dest_switch, v_lane); remove_temp_depend_for_sp(p_lash, dest_switch, i, v_lane); v_lane++; } else { set_temp_depend_to_permanent_for_sp(p_lash, i, dest_switch, v_lane); set_temp_depend_to_permanent_for_sp(p_lash, dest_switch, i, v_lane); stop = 1; p_lash->num_mst_in_lane[v_lane]++; p_lash->num_mst_in_lane[v_lane]++; } } switches[i]->routing_table[dest_switch].lane = v_lane + start_vl; switches[dest_switch]->routing_table[i].lane = v_lane + start_vl; if (cycle_found == 1 || cycle_found2 == 1) { if (++lanes_needed > p_lash->vl_min) goto Error_Not_Enough_Lanes; if (generate_cdg_for_sp(p_lash, i, dest_switch, v_lane) || generate_cdg_for_sp(p_lash, dest_switch, i, v_lane)) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D08: generate_cdg_for_sp failed\n"); goto Exit; } set_temp_depend_to_permanent_for_sp(p_lash, i, dest_switch, v_lane); set_temp_depend_to_permanent_for_sp(p_lash, dest_switch, i, v_lane); p_lash->num_mst_in_lane[v_lane]++; p_lash->num_mst_in_lane[v_lane]++; } p_lash->virtual_location[i][dest_switch][v_lane] = 1; p_lash->virtual_location[dest_switch][i][v_lane] = 1; switch_bitmap[i * num_switches + dest_switch] = 1; switch_bitmap[dest_switch * num_switches + i] = 1; } } for (i = 0; i < lanes_needed; i++) OSM_LOG(p_log, OSM_LOG_INFO, "Lanes in layer %d: %d\n", i, p_lash->num_mst_in_lane[i]); OSM_LOG(p_log, OSM_LOG_INFO, "Lanes needed: %d, Balancing\n", lanes_needed); if (balance_virtual_lanes(p_lash, lanes_needed)) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D09: Balancing failed\n"); goto Exit; } for (i = 0; i < lanes_needed; i++) OSM_LOG(p_log, OSM_LOG_INFO, "Lanes in layer %d: %d\n", i, p_lash->num_mst_in_lane[i]); status = 0; goto Exit; Error_Not_Enough_Lanes: OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D02: " "Lane requirements (%d) exceed available lanes (%d)" " with starting lane (%d)\n", lanes_needed, p_lash->vl_min, start_vl); Exit: if (switch_bitmap) free(switch_bitmap); OSM_LOG_EXIT(p_log); return status; }
static int balance_virtual_lanes(lash_t * p_lash, unsigned lanes_needed) { unsigned num_switches = p_lash->num_switches; cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix; int *num_mst_in_lane = p_lash->num_mst_in_lane; int ***virtual_location = p_lash->virtual_location; int min_filled_lane, max_filled_lane, trials; int old_min_filled_lane, old_max_filled_lane, new_num_min_lane, new_num_max_lane; unsigned int i, j; int src, dest, start, next_switch, output_link; int next_switch2, output_link2; int stop = 0, cycle_found; int cycle_found2; unsigned start_vl = p_lash->p_osm->subn.opt.lash_start_vl; max_filled_lane = 0; min_filled_lane = lanes_needed - 1; trials = num_mst_in_lane[max_filled_lane]; if (lanes_needed == 1) stop = 1; while (stop == 0) { src = abs(rand()) % (num_switches); dest = abs(rand()) % (num_switches); while (virtual_location[src][dest][max_filled_lane] != 1) { start = dest; if (dest == num_switches - 1) dest = 0; else dest++; while (dest != start && virtual_location[src][dest][max_filled_lane] != 1) { if (dest == num_switches - 1) dest = 0; else dest++; } if (virtual_location[src][dest][max_filled_lane] != 1) { if (src == num_switches - 1) src = 0; else src++; } } if (generate_cdg_for_sp(p_lash, src, dest, min_filled_lane) || generate_cdg_for_sp(p_lash, dest, src, min_filled_lane)) return -1; output_link = p_lash->switches[src]->routing_table[dest].out_link; next_switch = get_next_switch(p_lash, src, output_link); output_link2 = p_lash->switches[dest]->routing_table[src].out_link; next_switch2 = get_next_switch(p_lash, dest, output_link2); CL_ASSERT(cdg_vertex_matrix[min_filled_lane][src][next_switch] != NULL); CL_ASSERT(cdg_vertex_matrix[min_filled_lane][dest][next_switch2] != NULL); cycle_found = cycle_exists(cdg_vertex_matrix[min_filled_lane][src][next_switch], NULL, NULL, 1); cycle_found2 = cycle_exists(cdg_vertex_matrix[min_filled_lane][dest][next_switch2], NULL, NULL, 1); for (i = 0; i < num_switches; i++) for (j = 0; j < num_switches; j++) if (cdg_vertex_matrix[min_filled_lane][i][j] != NULL) { cdg_vertex_matrix[min_filled_lane][i][j]->visiting_number = 0; cdg_vertex_matrix[min_filled_lane][i][j]->seen = 0; } if (cycle_found == 1 || cycle_found2 == 1) { remove_temp_depend_for_sp(p_lash, src, dest, min_filled_lane); remove_temp_depend_for_sp(p_lash, dest, src, min_filled_lane); virtual_location[src][dest][max_filled_lane] = 2; virtual_location[dest][src][max_filled_lane] = 2; trials--; trials--; } else { set_temp_depend_to_permanent_for_sp(p_lash, src, dest, min_filled_lane); set_temp_depend_to_permanent_for_sp(p_lash, dest, src, min_filled_lane); num_mst_in_lane[max_filled_lane]--; num_mst_in_lane[max_filled_lane]--; num_mst_in_lane[min_filled_lane]++; num_mst_in_lane[min_filled_lane]++; remove_semipermanent_depend_for_sp(p_lash, src, dest, max_filled_lane); remove_semipermanent_depend_for_sp(p_lash, dest, src, max_filled_lane); virtual_location[src][dest][max_filled_lane] = 0; virtual_location[dest][src][max_filled_lane] = 0; virtual_location[src][dest][min_filled_lane] = 1; virtual_location[dest][src][min_filled_lane] = 1; p_lash->switches[src]->routing_table[dest].lane = min_filled_lane + start_vl; p_lash->switches[dest]->routing_table[src].lane = min_filled_lane + start_vl; } if (trials == 0) stop = 1; else { if (num_mst_in_lane[max_filled_lane] - num_mst_in_lane[min_filled_lane] < p_lash->balance_limit) stop = 1; } old_min_filled_lane = min_filled_lane; old_max_filled_lane = max_filled_lane; new_num_min_lane = MAX_INT; new_num_max_lane = 0; for (i = 0; i < lanes_needed; i++) { if (num_mst_in_lane[i] < new_num_min_lane) { new_num_min_lane = num_mst_in_lane[i]; min_filled_lane = i; } if (num_mst_in_lane[i] > new_num_max_lane) { new_num_max_lane = num_mst_in_lane[i]; max_filled_lane = i; } } if (old_min_filled_lane != min_filled_lane) { trials = num_mst_in_lane[max_filled_lane]; for (i = 0; i < num_switches; i++) for (j = 0; j < num_switches; j++) if (virtual_location[i][j][max_filled_lane] == 2) virtual_location[i][j][max_filled_lane] = 1; } if (old_max_filled_lane != max_filled_lane) { trials = num_mst_in_lane[max_filled_lane]; for (i = 0; i < num_switches; i++) for (j = 0; j < num_switches; j++) if (virtual_location[i][j][old_max_filled_lane] == 2) virtual_location[i][j][old_max_filled_lane] = 1; } } return 0; }