int tMPI_Abort(tMPI_Comm comm, int errorcode) { #ifdef TMPI_TRACE tMPI_Trace_print("tMPI_Abort(%p, %d)", comm, errorcode); #endif #if 0 /* we abort(). This way we can run a debugger on it */ fprintf(stderr, "tMPI_Abort called with error code %d", errorcode); if (comm == TMPI_COMM_WORLD) { fprintf(stderr, " on TMPI_COMM_WORLD"); } fprintf(stderr, "\n"); fflush(stdout); abort(); #else /* we just kill all threads, but not the main process */ if (tMPI_Is_master()) { if (comm == TMPI_COMM_WORLD) { fprintf(stderr, "tMPI_Abort called on TMPI_COMM_WORLD main with errorcode=%d\n", errorcode); } else { fprintf(stderr, "tMPI_Abort called on main thread with errorcode=%d\n", errorcode); } fflush(stderr); exit(errorcode); } else { int *ret; /* kill myself */ fprintf(stderr, "tMPI_Abort called with error code %d on thread %d\n", errorcode, tMPI_This_threadnr()); fflush(stderr); ret = (int*)malloc(sizeof(int)); tMPI_Thread_exit(ret); } #endif return TMPI_SUCCESS; }
int tMPI_Finalize(void) { int i; #ifdef TMPI_TRACE tMPI_Trace_print("tMPI_Finalize()"); #endif #ifdef TMPI_DEBUG printf("%5d: tMPI_Finalize called\n", tMPI_This_threadnr()); fflush(stdout); #endif #ifdef TMPI_PROFILE { struct tmpi_thread *cur=tMPI_Get_current(); tMPI_Profile_stop( &(cur->profile) ); tMPI_Thread_barrier_wait( &(tmpi_global->barrier) ); if (tMPI_Is_master()) { tMPI_Profiles_summarize(Nthreads, threads); } } #endif tMPI_Thread_barrier_wait( &(tmpi_global->barrier) ); if (tMPI_Is_master()) { /* we just wait for all threads to finish; the order isn't very relevant, as all threads should arrive at their endpoints soon. */ for(i=1;i<Nthreads;i++) { if (tMPI_Thread_join(threads[i].thread_id, NULL)) { tMPI_Error(TMPI_COMM_WORLD, TMPI_ERR_FINALIZE); } tMPI_Thread_destroy(&(threads[i])); } /* at this point, we are the only thread left, so we can destroy the global structures with impunity. */ tMPI_Thread_destroy(&(threads[0])); free(threads); tMPI_Thread_key_delete(id_key); /* de-allocate all the comm stuctures. */ { tMPI_Comm cur=TMPI_COMM_WORLD->next; while(cur && (cur!=TMPI_COMM_WORLD) ) { tMPI_Comm next=cur->next; tMPI_Comm_destroy(cur); cur=next; } tMPI_Comm_destroy(TMPI_COMM_WORLD); } tMPI_Group_free(&TMPI_GROUP_EMPTY); threads=0; TMPI_COMM_WORLD=NULL; TMPI_GROUP_EMPTY=NULL; Nthreads=0; /* deallocate the 'global' structure */ tMPI_Global_destroy(tmpi_global); free(tmpi_global); tmpi_finalized=TRUE; } else { tMPI_Thread_exit(0); } return TMPI_SUCCESS; }