int tMPI_Get_N(int *argc, char ***argv, const char *optname, int *nthreads) { int i; int ret = TMPI_SUCCESS; *nthreads = 0; if (!optname) { i = 0; } else { for (i = 1; i < *argc; i++) { if (strcmp(optname, (*argv)[i]) == 0) { break; } } } if (i+1 < (*argc)) { /* the number of processes is an argument */ char *end; *nthreads = strtol((*argv)[i+1], &end, 10); if (!end || (*end != 0) ) { *nthreads = 0; ret = TMPI_FAILURE; } } if (*nthreads < 1) { int nth = tMPI_Thread_get_hw_number(); if (nth < 1) { nth = 1; /* make sure it's at least 1 */ } *nthreads = nth; } return ret; }
int tMPI_Init_fn(int main_thread_returns, int N, void (*start_function)(void*), void *arg) { #ifdef TMPI_TRACE tMPI_Trace_print("tMPI_Init_fn(%d, %p, %p)", N, start_function, arg); #endif if (N<1) { N=tMPI_Thread_get_hw_number(); if (N<1) N=1; /*because that's what the fn returns if it doesn't know*/ } if (TMPI_COMM_WORLD==0 && N>=1) /* we're the main process */ { tMPI_Start_threads(main_thread_returns, N, 0, 0, start_function, arg, NULL); } return TMPI_SUCCESS; }
void tMPI_Start_threads(tmpi_bool main_returns, int N, int *argc, char ***argv, void (*start_fn)(void*), void *start_arg, int (*start_fn_main)(int, char**)) { #ifdef TMPI_TRACE tMPI_Trace_print("tMPI_Start_threads(%d, %p, %p, %p, %p)", N, argc, argv, start_fn, start_arg); #endif if (N>0) { int i; int set_affinity=FALSE; tmpi_finalized=FALSE; Nthreads=N; /* allocate global data */ tmpi_global=(struct tmpi_global*) tMPI_Malloc(sizeof(struct tmpi_global)); tMPI_Global_init(tmpi_global, N); /* allocate world and thread data */ threads=(struct tmpi_thread*)tMPI_Malloc(sizeof(struct tmpi_thread)*N); TMPI_COMM_WORLD=tMPI_Comm_alloc(NULL, N); TMPI_GROUP_EMPTY=tMPI_Group_alloc(); if (tMPI_Thread_key_create(&id_key, NULL)) { tMPI_Error(TMPI_COMM_WORLD, TMPI_ERR_INIT); } for(i=0;i<N;i++) { TMPI_COMM_WORLD->grp.peers[i]=&(threads[i]); /* copy argc, argv */ if (argc && argv) { int j; threads[i].argc=*argc; threads[i].argv=(char**)tMPI_Malloc(threads[i].argc* sizeof(char*)); for(j=0;j<threads[i].argc;j++) { #if ! (defined( _WIN32 ) || defined( _WIN64 ) ) threads[i].argv[j]=strdup( (*argv)[j] ); #else threads[i].argv[j]=_strdup( (*argv)[j] ); #endif } } else { threads[i].argc=0; threads[i].argv=NULL; } threads[i].start_fn=start_fn; threads[i].start_fn_main=start_fn_main; threads[i].start_arg=start_arg; } /* now check whether to set affinity */ #ifdef TMPI_THREAD_AFFINITY { int nhw=tMPI_Thread_get_hw_number(); if ((nhw > 1) && (nhw == N)) { set_affinity=TRUE; } } #endif for(i=1;i<N;i++) /* zero is the main thread */ { int ret; if (set_affinity) { ret=tMPI_Thread_create_aff(&(threads[i].thread_id), tMPI_Thread_starter, (void*)&(threads[i]) ) ; } else { ret=tMPI_Thread_create(&(threads[i].thread_id), tMPI_Thread_starter, (void*)&(threads[i]) ) ; } if(ret) { tMPI_Error(TMPI_COMM_WORLD, TMPI_ERR_INIT); } } /* the main thread now also runs start_fn if we don't want it to return */ if (!main_returns) tMPI_Thread_starter((void*)&(threads[0])); else tMPI_Thread_init(&(threads[0])); } }