/* Registers a callback with the process waiter, but will not start the process waiter * if it is not running. Note that this will not stop the process waiter if it is already * running. * * Callbacks will be removed if their watched pid is greater than -1 and the received * pid from 'wait()' equals the watched pid. If the watched pid is less than 0, then * the callback will never be removed from the event list unless manually removed by * calling 'proc_waiter_deregister()'. * * Parameters: * pid: The process ID returned by 'wait()' that should call 'proc_exited' callback. * If <0, the callback will be called for any PID that is returned by 'wait()'. * proc_exited: The callback called when 'wait()' returns a PID that matches 'pid'. * user_data: Data to be passed to the callback when called. */ alib_error proc_waiter_register_no_start(int pid, proc_exited_cb proc_exited, void* user_data) { if(!proc_waiter_is_initialized()) return(ALIB_STATE_ERR); int err; proc_waiter* pw = malloc(sizeof(proc_waiter)); if(!pw)return(ALIB_MEM_ERR); pw->pid = pid; pw->cb = proc_exited; pw->user_data = user_data; /* Ensure our globals are allocated. */ if((err = allocate_globals())) goto f_error; /* Add the proc waiter to the list. */ if(!ArrayList_add(PROC_WAITER_CB_LIST, pw)) { err = ALIB_MEM_ERR; goto f_error; } else pthread_cond_broadcast(PROC_WAITER_T_COND); return(ALIB_OK); f_error: free(pw); return(err); }
/* Thread safe version of 'proc_waiter_register()'. * * Locks the ArrayList mutex. */ alib_error proc_waiter_register_tsafe(int pid, proc_exited_cb proc_exited, void* user_data) { allocate_globals(); alib_error err; ArrayList_lock(PROC_WAITER_CB_LIST); err = proc_waiter_register(pid, proc_exited, user_data); ArrayList_unlock(PROC_WAITER_CB_LIST); return(err); }
int main(int argc, char *argv[]) { uint32_t num_objs = 0; uint32_t num_snaps = 0; uint32_t iters = 0; printf("Usage: <prog> <num_objs> <num_snaps> <num_iters>\n"); if (argc >= 2) { num_objs = atoi(argv[1]); } if ((num_objs == 0) || (num_objs > MAX_OBJECTS)) { printf("Setting num_objs to MAX_OBJECTS=%u\n", MAX_OBJECTS); fflush(stdout); num_objs = MAX_OBJECTS; } if (argc >= 3) { num_snaps = atoi(argv[2]); } if ((num_snaps == 0) || (num_snaps > MAX_SNAPSHOTS)) { printf("Setting num_snaps to %u\n", MAX_SNAPSHOTS); fflush(stdout); num_snaps = MAX_SNAPSHOTS; } if (argc >= 4) { iters = atoi(argv[3]); } if (iters == 0) { iters = num_snaps + 1; } allocate_globals(num_objs); printf("Starting test with %u objs %u snapshots and %u iterations\n", num_objs, num_snaps, iters); fflush(stdout); ZSInit(&zs_state); do_rw_test(num_objs, iters, num_snaps); do_rangeupdate_test(num_objs, iters, num_snaps); do_delete_test(num_objs, iters, num_snaps); do_quiesce_test(num_objs, iters, num_snaps); ZSShutdown(zs_state); return 0; }
/* Starts the thread. If the thread is already running * ALIB_OK will be returned. * * Waiting for child processes to close is handled on a separate thread. */ alib_error proc_waiter_start() { int err = allocate_globals(); if(err)return(err); /* Make sure we don't call start at the same time from two different threads. */ pthread_mutex_lock(PROC_WAITER_MUTEX); /* Setup the flags as needed. */ flag_lower(&PROC_WAITER_FLAG_POLE, THREAD_STOP); if((PROC_WAITER_FLAG_POLE & THREAD_IS_RUNNING) && (PROC_WAITER_FLAG_POLE & THREAD_CREATED)) { err = ALIB_OK; goto f_unlock; } /* Check to see if we are still running. */ if(PROC_WAITER_FLAG_POLE & THREAD_IS_RUNNING) proc_waiter_stop_now(); /* Ensure our thread is cleaned up. */ if(PROC_WAITER_FLAG_POLE & THREAD_CREATED) pthread_join(*PROC_WAITER_THREAD, NULL); /* Raise the THREAD_IS_RUNNING flag before creating the thread so that the flag * will never misrepresent the state of the thread. */ flag_raise(&PROC_WAITER_FLAG_POLE, THREAD_IS_RUNNING | THREAD_CREATED); if(pthread_create(PROC_WAITER_THREAD, NULL, thread_proc, NULL)) { flag_lower(&PROC_WAITER_FLAG_POLE, THREAD_IS_RUNNING | THREAD_CREATED); err = ALIB_THREAD_ERR; goto f_unlock; } f_unlock: pthread_mutex_unlock(PROC_WAITER_MUTEX); return(err); }
int spai (matrix *A, matrix **spai_mat, FILE *messages_arg, /* file for warning messages */ double epsilon_arg, /* tolerance */ int nbsteps_arg, /* max number of "improvement" steps per line */ int max_arg, /* max dimensions of I, q, etc. */ int maxnew_arg, /* max number of new entries per step */ int cache_size_arg, /* one of (1,2,3,4,5,6) indicting size of cache */ /* cache_size == 0 indicates no caching */ int verbose_arg, int spar_arg, int lower_diag_arg, int upper_diag_arg, double tau_arg) { matrix *M; int col,ierr; int cache_sizes[6]; /* Only create resplot for the numprocs=1 case. */ if (debug && (A->numprocs == 1)) { resplot_fptr = fopen("resplot","w"); fprintf(resplot_fptr, "ep=%5.5lf ns=%d mn=%d bs=%d\n", epsilon_arg,nbsteps_arg,maxnew_arg,A->bs); fprintf(resplot_fptr,"\n"); fprintf(resplot_fptr,"scol: scalar column number\n"); fprintf(resplot_fptr,"srn: scalar resnorm\n"); fprintf(resplot_fptr,"bcol: block column number\n"); fprintf(resplot_fptr,"brn: block resnorm\n"); fprintf(resplot_fptr,"* indicates epsilon not attained\n"); fprintf(resplot_fptr,"\n"); fprintf(resplot_fptr," scol srn bcol brn\n"); } start_col = 0; num_bad_cols = 0; cache_sizes[0] = 101; cache_sizes[1] = 503; cache_sizes[2] = 2503; cache_sizes[3] = 12503; cache_sizes[4] = 62501; cache_sizes[5] = 104743; if (verbose_arg && !A->myid) { if (spar_arg == 0) printf("\n\nComputing SPAI: epsilon = %f\n",epsilon_arg); else if (spar_arg == 1) printf("\n\nComputing SPAI: tau = %f\n",tau_arg); else if (spar_arg == 2) printf("\n\nComputing SPAI: # diagonals = %d\n", lower_diag_arg+upper_diag_arg+1); fflush(stdout); } epsilon = epsilon_arg; message = messages_arg; maxnew = maxnew_arg; max_dim = max_arg; /* Determine maximum number of scalar nonzeros for any column of M */ if (spar_arg == 0) { nbsteps = nbsteps_arg; maxapi = A->max_block_size * (1 + maxnew*nbsteps); } else if(spar_arg == 1) { nbsteps = A->maxnz; maxapi = A->max_block_size * (1 + nbsteps); } else { nbsteps = lower_diag_arg+upper_diag_arg+1; maxapi = A->max_block_size * (1 + nbsteps); } allocate_globals(A); #ifdef MPI MPI_Barrier(A->comm); #endif if ((cache_size_arg < 0) || (cache_size_arg > 6)) { fprintf(stderr,"illegal cache size in spai\n"); exit(1); } if (cache_size_arg > 0) ht = init_hash_table(cache_sizes[cache_size_arg-1]); M = clone_matrix(A); ndone = 0; Im_done = 0; all_done = 0; next_line = 0; /* Timing of SPAI starts here. In a "real production" code everything before this could be static. */ if (verbose_arg) start_timer(ident_spai); if ((ierr = precompute_column_square_inverses(A)) != 0) return ierr; #ifdef MPI MPI_Barrier(A->comm); #endif for (;;) { col = grab_Mline(A, M, A->comm); if (debug && col >= 0) { fprintf(fptr_dbg,"col=%d of %d\n",col,A->n); fflush(fptr_dbg); } if (col < 0 ) break; if ((ierr = spai_line(A,col,spar_arg,lower_diag_arg,upper_diag_arg,tau_arg,M)) != 0) return ierr; } #ifdef MPI say_Im_done(A,M); do { com_server(A,M); } while (! all_done); MPI_Barrier(A->comm); #endif #ifdef MPI MPI_Barrier(A->comm); #endif if (verbose_arg) { stop_timer(ident_spai); report_times(ident_spai,"spai",0,A->comm); } free_globals(nbsteps); free_hash_table(ht); if (resplot_fptr) fclose(resplot_fptr); *spai_mat = M; return 0; }