1e5c89e4eSSatish Balay /* 2e5c89e4eSSatish Balay 3e5c89e4eSSatish Balay This file defines part of the initialization of PETSc 4e5c89e4eSSatish Balay 5e5c89e4eSSatish Balay This file uses regular malloc and free because it cannot know 6e5c89e4eSSatish Balay what malloc is being used until it has already processed the input. 7e5c89e4eSSatish Balay */ 8e5c89e4eSSatish Balay 951d315f7SKerry Stevens #define _GNU_SOURCE 1051d315f7SKerry Stevens #include <sched.h> 11c6db04a5SJed Brown #include <petscsys.h> /*I "petscsys.h" I*/ 12ba61063dSBarry Smith #if defined(PETSC_USE_PTHREAD) 1351dcc849SKerry Stevens #include <pthread.h> 14ba61063dSBarry Smith #endif 15ba61063dSBarry Smith #if defined(PETSC_HAVE_SYS_SYSINFO_H) 1651d315f7SKerry Stevens #include <sys/sysinfo.h> 17ba61063dSBarry Smith #endif 1851d315f7SKerry Stevens #include <unistd.h> 19e5c89e4eSSatish Balay #if defined(PETSC_HAVE_STDLIB_H) 20e5c89e4eSSatish Balay #include <stdlib.h> 21e5c89e4eSSatish Balay #endif 22e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H) 23e5c89e4eSSatish Balay #include <malloc.h> 24e5c89e4eSSatish Balay #endif 25555d055bSBarry Smith #if defined(PETSC_HAVE_VALGRIND) 26555d055bSBarry Smith #include <valgrind/valgrind.h> 27555d055bSBarry Smith #endif 28555d055bSBarry Smith 29e5c89e4eSSatish Balay /* ------------------------Nasty global variables -------------------------------*/ 30e5c89e4eSSatish Balay /* 31e5c89e4eSSatish Balay Indicates if PETSc started up MPI, or it was 32e5c89e4eSSatish Balay already started before PETSc was initialized. 33e5c89e4eSSatish Balay */ 347087cfbeSBarry Smith PetscBool PetscBeganMPI = PETSC_FALSE; 357087cfbeSBarry Smith PetscBool PetscInitializeCalled = PETSC_FALSE; 367087cfbeSBarry Smith PetscBool PetscFinalizeCalled = PETSC_FALSE; 3751dcc849SKerry Stevens PetscBool PetscUseThreadPool = PETSC_FALSE; 3851dcc849SKerry Stevens PetscBool PetscThreadGo = PETSC_TRUE; 397087cfbeSBarry Smith PetscMPIInt PetscGlobalRank = -1; 407087cfbeSBarry Smith PetscMPIInt PetscGlobalSize = -1; 41ba61063dSBarry Smith 42ba61063dSBarry Smith #if defined(PETSC_USE_PTHREAD_CLASSES) 4351dcc849SKerry Stevens PetscMPIInt PetscMaxThreads = 2; 4451dcc849SKerry Stevens pthread_t* PetscThreadPoint; 45ba61063dSBarry Smith #if defined(PETSC_HAVE_PTHREAD_BARRIER) 46ba61063dSBarry Smith pthread_barrier_t* BarrPoint; /* used by 'true' thread pool */ 47ba61063dSBarry Smith #endif 4851d315f7SKerry Stevens PetscErrorCode ithreaderr = 0; 49f09cb4aaSKerry Stevens int* pVal; 5051dcc849SKerry Stevens 51ba61063dSBarry Smith #define CACHE_LINE_SIZE 64 /* used by 'chain', 'main','tree' thread pools */ 5251d315f7SKerry Stevens int* ThreadCoreAffinity; 5351d315f7SKerry Stevens 54ba61063dSBarry Smith typedef enum {JobInitiated,ThreadsWorking,JobCompleted} estat; /* used by 'chain','tree' thread pool */ 5551d315f7SKerry Stevens 5651d315f7SKerry Stevens typedef struct { 5751d315f7SKerry Stevens pthread_mutex_t** mutexarray; 5851d315f7SKerry Stevens pthread_cond_t** cond1array; 5951d315f7SKerry Stevens pthread_cond_t** cond2array; 6051d315f7SKerry Stevens void* (*pfunc)(void*); 6151d315f7SKerry Stevens void** pdata; 6251d315f7SKerry Stevens PetscBool startJob; 6351d315f7SKerry Stevens estat eJobStat; 6451d315f7SKerry Stevens PetscBool** arrThreadStarted; 6551d315f7SKerry Stevens PetscBool** arrThreadReady; 6651d315f7SKerry Stevens } sjob_tree; 6751d315f7SKerry Stevens sjob_tree job_tree; 6851d315f7SKerry Stevens typedef struct { 6951d315f7SKerry Stevens pthread_mutex_t** mutexarray; 7051d315f7SKerry Stevens pthread_cond_t** cond1array; 7151d315f7SKerry Stevens pthread_cond_t** cond2array; 7251d315f7SKerry Stevens void* (*pfunc)(void*); 7351d315f7SKerry Stevens void** pdata; 7451d315f7SKerry Stevens PetscBool** arrThreadReady; 7551d315f7SKerry Stevens } sjob_main; 7651d315f7SKerry Stevens sjob_main job_main; 7751d315f7SKerry Stevens typedef struct { 7851d315f7SKerry Stevens pthread_mutex_t** mutexarray; 7951d315f7SKerry Stevens pthread_cond_t** cond1array; 8051d315f7SKerry Stevens pthread_cond_t** cond2array; 8151d315f7SKerry Stevens void* (*pfunc)(void*); 8251d315f7SKerry Stevens void** pdata; 8351d315f7SKerry Stevens PetscBool startJob; 8451d315f7SKerry Stevens estat eJobStat; 8551d315f7SKerry Stevens PetscBool** arrThreadStarted; 8651d315f7SKerry Stevens PetscBool** arrThreadReady; 8751d315f7SKerry Stevens } sjob_chain; 8851d315f7SKerry Stevens sjob_chain job_chain; 89ba61063dSBarry Smith #if defined(PETSC_HAVE_PTHREAD_BARRIER) 9051dcc849SKerry Stevens typedef struct { 9151dcc849SKerry Stevens pthread_mutex_t mutex; 9251dcc849SKerry Stevens pthread_cond_t cond; 9351dcc849SKerry Stevens void* (*pfunc)(void*); 9451dcc849SKerry Stevens void** pdata; 9551dcc849SKerry Stevens pthread_barrier_t* pbarr; 9651dcc849SKerry Stevens int iNumJobThreads; 9751dcc849SKerry Stevens int iNumReadyThreads; 9851dcc849SKerry Stevens PetscBool startJob; 9951d315f7SKerry Stevens } sjob_true; 10051d315f7SKerry Stevens sjob_true job_true = {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER,NULL,NULL,NULL,0,0,PETSC_FALSE}; 101ba61063dSBarry Smith #endif 10251dcc849SKerry Stevens 103ba61063dSBarry Smith pthread_cond_t main_cond = PTHREAD_COND_INITIALIZER; /* used by 'true', 'chain','tree' thread pools */ 104ba61063dSBarry Smith char* arrmutex; /* used by 'chain','main','tree' thread pools */ 105ba61063dSBarry Smith char* arrcond1; /* used by 'chain','main','tree' thread pools */ 106ba61063dSBarry Smith char* arrcond2; /* used by 'chain','main','tree' thread pools */ 107ba61063dSBarry Smith char* arrstart; /* used by 'chain','main','tree' thread pools */ 108ba61063dSBarry Smith char* arrready; /* used by 'chain','main','tree' thread pools */ 10951dcc849SKerry Stevens 11051d315f7SKerry Stevens /* Function Pointers */ 11151d315f7SKerry Stevens void* (*PetscThreadFunc)(void*) = NULL; 11251d315f7SKerry Stevens void* (*PetscThreadInitialize)(PetscInt) = NULL; 11351d315f7SKerry Stevens PetscErrorCode (*PetscThreadFinalize)(void) = NULL; 11451d315f7SKerry Stevens void (*MainWait)(void) = NULL; 11551d315f7SKerry Stevens PetscErrorCode (*MainJob)(void* (*pFunc)(void*),void**,PetscInt) = NULL; 11651d315f7SKerry Stevens /**** Tree Functions ****/ 11751d315f7SKerry Stevens void* PetscThreadFunc_Tree(void*); 11851d315f7SKerry Stevens void* PetscThreadInitialize_Tree(PetscInt); 11951d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Tree(void); 12051d315f7SKerry Stevens void MainWait_Tree(void); 12151d315f7SKerry Stevens PetscErrorCode MainJob_Tree(void* (*pFunc)(void*),void**,PetscInt); 12251d315f7SKerry Stevens /**** Main Functions ****/ 12351d315f7SKerry Stevens void* PetscThreadFunc_Main(void*); 12451d315f7SKerry Stevens void* PetscThreadInitialize_Main(PetscInt); 12551d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Main(void); 12651d315f7SKerry Stevens void MainWait_Main(void); 12751d315f7SKerry Stevens PetscErrorCode MainJob_Main(void* (*pFunc)(void*),void**,PetscInt); 12851d315f7SKerry Stevens /**** Chain Functions ****/ 12951d315f7SKerry Stevens void* PetscThreadFunc_Chain(void*); 13051d315f7SKerry Stevens void* PetscThreadInitialize_Chain(PetscInt); 13151d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Chain(void); 13251d315f7SKerry Stevens void MainWait_Chain(void); 13351d315f7SKerry Stevens PetscErrorCode MainJob_Chain(void* (*pFunc)(void*),void**,PetscInt); 13451d315f7SKerry Stevens /**** True Functions ****/ 13551d315f7SKerry Stevens void* PetscThreadFunc_True(void*); 13651d315f7SKerry Stevens void* PetscThreadInitialize_True(PetscInt); 13751d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_True(void); 13851d315f7SKerry Stevens void MainWait_True(void); 13951d315f7SKerry Stevens PetscErrorCode MainJob_True(void* (*pFunc)(void*),void**,PetscInt); 14051d315f7SKerry Stevens /**** ****/ 14151d315f7SKerry Stevens 14251dcc849SKerry Stevens void* FuncFinish(void*); 1430ca81413SKerry Stevens void* PetscThreadRun(MPI_Comm Comm,void* (*pFunc)(void*),int,pthread_t*,void**); 1440ca81413SKerry Stevens void* PetscThreadStop(MPI_Comm Comm,int,pthread_t*); 145ba61063dSBarry Smith #endif 146e5c89e4eSSatish Balay 147e5c89e4eSSatish Balay #if defined(PETSC_USE_COMPLEX) 148e5c89e4eSSatish Balay #if defined(PETSC_COMPLEX_INSTANTIATE) 149e5c89e4eSSatish Balay template <> class std::complex<double>; /* instantiate complex template class */ 150e5c89e4eSSatish Balay #endif 1512c876bd9SBarry Smith #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX) 1527087cfbeSBarry Smith MPI_Datatype MPI_C_DOUBLE_COMPLEX; 1537087cfbeSBarry Smith MPI_Datatype MPI_C_COMPLEX; 1542c876bd9SBarry Smith #endif 1557087cfbeSBarry Smith PetscScalar PETSC_i; 156e5c89e4eSSatish Balay #else 1577087cfbeSBarry Smith PetscScalar PETSC_i = 0.0; 158e5c89e4eSSatish Balay #endif 159ce63c4c1SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128) 160c90a1750SBarry Smith MPI_Datatype MPIU___FLOAT128 = 0; 161c90a1750SBarry Smith #endif 1627087cfbeSBarry Smith MPI_Datatype MPIU_2SCALAR = 0; 1637087cfbeSBarry Smith MPI_Datatype MPIU_2INT = 0; 16475567043SBarry Smith 165e5c89e4eSSatish Balay /* 166e5c89e4eSSatish Balay These are needed by petscbt.h 167e5c89e4eSSatish Balay */ 168c6db04a5SJed Brown #include <petscbt.h> 1697087cfbeSBarry Smith char _BT_mask = ' '; 1707087cfbeSBarry Smith char _BT_c = ' '; 1717087cfbeSBarry Smith PetscInt _BT_idx = 0; 172e5c89e4eSSatish Balay 173e5c89e4eSSatish Balay /* 174e5c89e4eSSatish Balay Function that is called to display all error messages 175e5c89e4eSSatish Balay */ 1767087cfbeSBarry Smith PetscErrorCode (*PetscErrorPrintf)(const char [],...) = PetscErrorPrintfDefault; 1777087cfbeSBarry Smith PetscErrorCode (*PetscHelpPrintf)(MPI_Comm,const char [],...) = PetscHelpPrintfDefault; 178238ccf28SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE) 1797087cfbeSBarry Smith PetscErrorCode (*PetscVFPrintf)(FILE*,const char[],va_list) = PetscVFPrintf_Matlab; 180238ccf28SShri Abhyankar #else 1817087cfbeSBarry Smith PetscErrorCode (*PetscVFPrintf)(FILE*,const char[],va_list) = PetscVFPrintfDefault; 182238ccf28SShri Abhyankar #endif 183bab1f7e6SVictor Minden /* 1848154be41SBarry Smith This is needed to turn on/off cusp synchronization */ 1858154be41SBarry Smith PetscBool synchronizeCUSP = PETSC_FALSE; 186bab1f7e6SVictor Minden 187e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/ 188e5c89e4eSSatish Balay /* 189e5c89e4eSSatish Balay Optional file where all PETSc output from various prints is saved 190e5c89e4eSSatish Balay */ 191e5c89e4eSSatish Balay FILE *petsc_history = PETSC_NULL; 192e5c89e4eSSatish Balay 193e5c89e4eSSatish Balay #undef __FUNCT__ 194f3dea69dSBarry Smith #define __FUNCT__ "PetscOpenHistoryFile" 1957087cfbeSBarry Smith PetscErrorCode PetscOpenHistoryFile(const char filename[],FILE **fd) 196e5c89e4eSSatish Balay { 197e5c89e4eSSatish Balay PetscErrorCode ierr; 198e5c89e4eSSatish Balay PetscMPIInt rank,size; 199e5c89e4eSSatish Balay char pfile[PETSC_MAX_PATH_LEN],pname[PETSC_MAX_PATH_LEN],fname[PETSC_MAX_PATH_LEN],date[64]; 200e5c89e4eSSatish Balay char version[256]; 201e5c89e4eSSatish Balay 202e5c89e4eSSatish Balay PetscFunctionBegin; 203e5c89e4eSSatish Balay ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); 204e5c89e4eSSatish Balay if (!rank) { 205e5c89e4eSSatish Balay char arch[10]; 206f56c2debSBarry Smith int err; 20788c29154SBarry Smith PetscViewer viewer; 208f56c2debSBarry Smith 209e5c89e4eSSatish Balay ierr = PetscGetArchType(arch,10);CHKERRQ(ierr); 210e5c89e4eSSatish Balay ierr = PetscGetDate(date,64);CHKERRQ(ierr); 211a523d312SBarry Smith ierr = PetscGetVersion(version,256);CHKERRQ(ierr); 212e5c89e4eSSatish Balay ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); 213e5c89e4eSSatish Balay if (filename) { 214e5c89e4eSSatish Balay ierr = PetscFixFilename(filename,fname);CHKERRQ(ierr); 215e5c89e4eSSatish Balay } else { 216e5c89e4eSSatish Balay ierr = PetscGetHomeDirectory(pfile,240);CHKERRQ(ierr); 217e5c89e4eSSatish Balay ierr = PetscStrcat(pfile,"/.petschistory");CHKERRQ(ierr); 218e5c89e4eSSatish Balay ierr = PetscFixFilename(pfile,fname);CHKERRQ(ierr); 219e5c89e4eSSatish Balay } 220e5c89e4eSSatish Balay 221e32f2f54SBarry Smith *fd = fopen(fname,"a"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file: %s",fname); 222e5c89e4eSSatish Balay ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr); 223e5c89e4eSSatish Balay ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"%s %s\n",version,date);CHKERRQ(ierr); 224e5c89e4eSSatish Balay ierr = PetscGetProgramName(pname,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 225e5c89e4eSSatish Balay ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"%s on a %s, %d proc. with options:\n",pname,arch,size);CHKERRQ(ierr); 22688c29154SBarry Smith ierr = PetscViewerASCIIOpenWithFILE(PETSC_COMM_WORLD,*fd,&viewer);CHKERRQ(ierr); 22788c29154SBarry Smith ierr = PetscOptionsView(viewer);CHKERRQ(ierr); 2286bf464f9SBarry Smith ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 229e5c89e4eSSatish Balay ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr); 230f56c2debSBarry Smith err = fflush(*fd); 231e32f2f54SBarry Smith if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 232e5c89e4eSSatish Balay } 233e5c89e4eSSatish Balay PetscFunctionReturn(0); 234e5c89e4eSSatish Balay } 235e5c89e4eSSatish Balay 236e5c89e4eSSatish Balay #undef __FUNCT__ 237f3dea69dSBarry Smith #define __FUNCT__ "PetscCloseHistoryFile" 2387087cfbeSBarry Smith PetscErrorCode PetscCloseHistoryFile(FILE **fd) 239e5c89e4eSSatish Balay { 240e5c89e4eSSatish Balay PetscErrorCode ierr; 241e5c89e4eSSatish Balay PetscMPIInt rank; 242e5c89e4eSSatish Balay char date[64]; 243f56c2debSBarry Smith int err; 244e5c89e4eSSatish Balay 245e5c89e4eSSatish Balay PetscFunctionBegin; 246e5c89e4eSSatish Balay ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); 247e5c89e4eSSatish Balay if (!rank) { 248e5c89e4eSSatish Balay ierr = PetscGetDate(date,64);CHKERRQ(ierr); 249e5c89e4eSSatish Balay ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr); 250e5c89e4eSSatish Balay ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"Finished at %s\n",date);CHKERRQ(ierr); 251e5c89e4eSSatish Balay ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr); 252f56c2debSBarry Smith err = fflush(*fd); 253e32f2f54SBarry Smith if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 254f56c2debSBarry Smith err = fclose(*fd); 255e32f2f54SBarry Smith if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file"); 256e5c89e4eSSatish Balay } 257e5c89e4eSSatish Balay PetscFunctionReturn(0); 258e5c89e4eSSatish Balay } 259e5c89e4eSSatish Balay 260e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/ 261e5c89e4eSSatish Balay 262e5c89e4eSSatish Balay /* 263e5c89e4eSSatish Balay This is ugly and probably belongs somewhere else, but I want to 264e5c89e4eSSatish Balay be able to put a true MPI abort error handler with command line args. 265e5c89e4eSSatish Balay 266e5c89e4eSSatish Balay This is so MPI errors in the debugger will leave all the stack 2673c311c98SBarry Smith frames. The default MP_Abort() cleans up and exits thus providing no useful information 2683c311c98SBarry Smith in the debugger hence we call abort() instead of MPI_Abort(). 269e5c89e4eSSatish Balay */ 270e5c89e4eSSatish Balay 271e5c89e4eSSatish Balay #undef __FUNCT__ 272e5c89e4eSSatish Balay #define __FUNCT__ "Petsc_MPI_AbortOnError" 273e5c89e4eSSatish Balay void Petsc_MPI_AbortOnError(MPI_Comm *comm,PetscMPIInt *flag) 274e5c89e4eSSatish Balay { 275e5c89e4eSSatish Balay PetscFunctionBegin; 2763c311c98SBarry Smith (*PetscErrorPrintf)("MPI error %d\n",*flag); 277e5c89e4eSSatish Balay abort(); 278e5c89e4eSSatish Balay } 279e5c89e4eSSatish Balay 280e5c89e4eSSatish Balay #undef __FUNCT__ 281e5c89e4eSSatish Balay #define __FUNCT__ "Petsc_MPI_DebuggerOnError" 282e5c89e4eSSatish Balay void Petsc_MPI_DebuggerOnError(MPI_Comm *comm,PetscMPIInt *flag) 283e5c89e4eSSatish Balay { 284e5c89e4eSSatish Balay PetscErrorCode ierr; 285e5c89e4eSSatish Balay 286e5c89e4eSSatish Balay PetscFunctionBegin; 2873c311c98SBarry Smith (*PetscErrorPrintf)("MPI error %d\n",*flag); 288e5c89e4eSSatish Balay ierr = PetscAttachDebugger(); 289e5c89e4eSSatish Balay if (ierr) { /* hopeless so get out */ 2903c311c98SBarry Smith MPI_Abort(*comm,*flag); 291e5c89e4eSSatish Balay } 292e5c89e4eSSatish Balay } 293e5c89e4eSSatish Balay 294e5c89e4eSSatish Balay #undef __FUNCT__ 295e5c89e4eSSatish Balay #define __FUNCT__ "PetscEnd" 296e5c89e4eSSatish Balay /*@C 297e5c89e4eSSatish Balay PetscEnd - Calls PetscFinalize() and then ends the program. This is useful if one 298e5c89e4eSSatish Balay wishes a clean exit somewhere deep in the program. 299e5c89e4eSSatish Balay 300e5c89e4eSSatish Balay Collective on PETSC_COMM_WORLD 301e5c89e4eSSatish Balay 302e5c89e4eSSatish Balay Options Database Keys are the same as for PetscFinalize() 303e5c89e4eSSatish Balay 304e5c89e4eSSatish Balay Level: advanced 305e5c89e4eSSatish Balay 306e5c89e4eSSatish Balay Note: 307e5c89e4eSSatish Balay See PetscInitialize() for more general runtime options. 308e5c89e4eSSatish Balay 30988c29154SBarry Smith .seealso: PetscInitialize(), PetscOptionsView(), PetscMallocDump(), PetscMPIDump(), PetscFinalize() 310e5c89e4eSSatish Balay @*/ 3117087cfbeSBarry Smith PetscErrorCode PetscEnd(void) 312e5c89e4eSSatish Balay { 313e5c89e4eSSatish Balay PetscFunctionBegin; 314e5c89e4eSSatish Balay PetscFinalize(); 315e5c89e4eSSatish Balay exit(0); 316e5c89e4eSSatish Balay return 0; 317e5c89e4eSSatish Balay } 318e5c89e4eSSatish Balay 319ace3abfcSBarry Smith PetscBool PetscOptionsPublish = PETSC_FALSE; 32009573ac7SBarry Smith extern PetscErrorCode PetscSetUseTrMalloc_Private(void); 321ace3abfcSBarry Smith extern PetscBool petscsetmallocvisited; 322e5c89e4eSSatish Balay static char emacsmachinename[256]; 323e5c89e4eSSatish Balay 324e5c89e4eSSatish Balay PetscErrorCode (*PetscExternalVersionFunction)(MPI_Comm) = 0; 325e5c89e4eSSatish Balay PetscErrorCode (*PetscExternalHelpFunction)(MPI_Comm) = 0; 326e5c89e4eSSatish Balay 327e5c89e4eSSatish Balay #undef __FUNCT__ 328e5c89e4eSSatish Balay #define __FUNCT__ "PetscSetHelpVersionFunctions" 329e5c89e4eSSatish Balay /*@C 330e5c89e4eSSatish Balay PetscSetHelpVersionFunctions - Sets functions that print help and version information 331e5c89e4eSSatish Balay before the PETSc help and version information is printed. Must call BEFORE PetscInitialize(). 332e5c89e4eSSatish Balay This routine enables a "higher-level" package that uses PETSc to print its messages first. 333e5c89e4eSSatish Balay 334e5c89e4eSSatish Balay Input Parameter: 335e5c89e4eSSatish Balay + help - the help function (may be PETSC_NULL) 336da93591fSBarry Smith - version - the version function (may be PETSC_NULL) 337e5c89e4eSSatish Balay 338e5c89e4eSSatish Balay Level: developer 339e5c89e4eSSatish Balay 340e5c89e4eSSatish Balay Concepts: package help message 341e5c89e4eSSatish Balay 342e5c89e4eSSatish Balay @*/ 3437087cfbeSBarry Smith PetscErrorCode PetscSetHelpVersionFunctions(PetscErrorCode (*help)(MPI_Comm),PetscErrorCode (*version)(MPI_Comm)) 344e5c89e4eSSatish Balay { 345e5c89e4eSSatish Balay PetscFunctionBegin; 346e5c89e4eSSatish Balay PetscExternalHelpFunction = help; 347e5c89e4eSSatish Balay PetscExternalVersionFunction = version; 348e5c89e4eSSatish Balay PetscFunctionReturn(0); 349e5c89e4eSSatish Balay } 350e5c89e4eSSatish Balay 351e5c89e4eSSatish Balay #undef __FUNCT__ 352e5c89e4eSSatish Balay #define __FUNCT__ "PetscOptionsCheckInitial_Private" 3537087cfbeSBarry Smith PetscErrorCode PetscOptionsCheckInitial_Private(void) 354e5c89e4eSSatish Balay { 355e5c89e4eSSatish Balay char string[64],mname[PETSC_MAX_PATH_LEN],*f; 356e5c89e4eSSatish Balay MPI_Comm comm = PETSC_COMM_WORLD; 357ace3abfcSBarry Smith PetscBool flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE,flg4 = PETSC_FALSE,flag,flgz,flgzout; 358e5c89e4eSSatish Balay PetscErrorCode ierr; 359a6d0e24fSJed Brown PetscReal si; 360e5c89e4eSSatish Balay int i; 361e5c89e4eSSatish Balay PetscMPIInt rank; 362e5c89e4eSSatish Balay char version[256]; 363e5c89e4eSSatish Balay 364e5c89e4eSSatish Balay PetscFunctionBegin; 365e5c89e4eSSatish Balay ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); 366e5c89e4eSSatish Balay 367e5c89e4eSSatish Balay /* 368e5c89e4eSSatish Balay Setup the memory management; support for tracing malloc() usage 369e5c89e4eSSatish Balay */ 3708bb29257SSatish Balay ierr = PetscOptionsHasName(PETSC_NULL,"-malloc_log",&flg3);CHKERRQ(ierr); 37181b192fdSBarry Smith #if defined(PETSC_USE_DEBUG) && !defined(PETSC_USE_PTHREAD) 372acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc",&flg1,&flg2);CHKERRQ(ierr); 373e5c89e4eSSatish Balay if ((!flg2 || flg1) && !petscsetmallocvisited) { 374555d055bSBarry Smith #if defined(PETSC_HAVE_VALGRIND) 375555d055bSBarry Smith if (flg2 || !(RUNNING_ON_VALGRIND)) { 376555d055bSBarry Smith /* turn off default -malloc if valgrind is being used */ 377555d055bSBarry Smith #endif 378e5c89e4eSSatish Balay ierr = PetscSetUseTrMalloc_Private();CHKERRQ(ierr); 379555d055bSBarry Smith #if defined(PETSC_HAVE_VALGRIND) 380555d055bSBarry Smith } 381555d055bSBarry Smith #endif 382e5c89e4eSSatish Balay } 383e5c89e4eSSatish Balay #else 384acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_dump",&flg1,PETSC_NULL);CHKERRQ(ierr); 385acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc",&flg2,PETSC_NULL);CHKERRQ(ierr); 386e5c89e4eSSatish Balay if (flg1 || flg2 || flg3) {ierr = PetscSetUseTrMalloc_Private();CHKERRQ(ierr);} 387e5c89e4eSSatish Balay #endif 388e5c89e4eSSatish Balay if (flg3) { 389e5c89e4eSSatish Balay ierr = PetscMallocSetDumpLog();CHKERRQ(ierr); 390e5c89e4eSSatish Balay } 39190d69ab7SBarry Smith flg1 = PETSC_FALSE; 392acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_debug",&flg1,PETSC_NULL);CHKERRQ(ierr); 393e5c89e4eSSatish Balay if (flg1) { 394e5c89e4eSSatish Balay ierr = PetscSetUseTrMalloc_Private();CHKERRQ(ierr); 395e5c89e4eSSatish Balay ierr = PetscMallocDebug(PETSC_TRUE);CHKERRQ(ierr); 396e5c89e4eSSatish Balay } 397e5c89e4eSSatish Balay 39890d69ab7SBarry Smith flg1 = PETSC_FALSE; 399acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_info",&flg1,PETSC_NULL);CHKERRQ(ierr); 4007783f70dSSatish Balay if (!flg1) { 40190d69ab7SBarry Smith flg1 = PETSC_FALSE; 402acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-memory_info",&flg1,PETSC_NULL);CHKERRQ(ierr); 4037783f70dSSatish Balay } 404e5c89e4eSSatish Balay if (flg1) { 405e5c89e4eSSatish Balay ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr); 406e5c89e4eSSatish Balay } 407e5c89e4eSSatish Balay 408e5c89e4eSSatish Balay /* 409e5c89e4eSSatish Balay Set the display variable for graphics 410e5c89e4eSSatish Balay */ 411e5c89e4eSSatish Balay ierr = PetscSetDisplay();CHKERRQ(ierr); 412e5c89e4eSSatish Balay 413*fc087633SBarry Smith #if defined(PETSC_USE_PTHREAD_CLASSES) 414e5c89e4eSSatish Balay /* 41551dcc849SKerry Stevens Determine whether user specified maximum number of threads 41651dcc849SKerry Stevens */ 41751dcc849SKerry Stevens ierr = PetscOptionsGetInt(PETSC_NULL,"-thread_max",&PetscMaxThreads,PETSC_NULL);CHKERRQ(ierr); 41851dcc849SKerry Stevens 41951dcc849SKerry Stevens /* 42051dcc849SKerry Stevens Determine whether to use thread pool 42151dcc849SKerry Stevens */ 42251dcc849SKerry Stevens ierr = PetscOptionsHasName(PETSC_NULL,"-use_thread_pool",&flg1);CHKERRQ(ierr); 42351dcc849SKerry Stevens if (flg1) { 42451dcc849SKerry Stevens PetscUseThreadPool = PETSC_TRUE; 42551d315f7SKerry Stevens PetscInt N_CORES = get_nprocs(); 42651d315f7SKerry Stevens ThreadCoreAffinity = (int*)malloc(N_CORES*sizeof(int)); 42751d315f7SKerry Stevens char tstr[9]; 42851d315f7SKerry Stevens char tbuf[2]; 42951d315f7SKerry Stevens strcpy(tstr,"-thread"); 43051d315f7SKerry Stevens for(i=0;i<PetscMaxThreads;i++) { 431ba61063dSBarry Smith ThreadCoreAffinity[i] = i; 43251d315f7SKerry Stevens sprintf(tbuf,"%d",i); 43351d315f7SKerry Stevens strcat(tstr,tbuf); 43451d315f7SKerry Stevens ierr = PetscOptionsHasName(PETSC_NULL,tstr,&flg1);CHKERRQ(ierr); 43551d315f7SKerry Stevens if(flg1) { 43651d315f7SKerry Stevens ierr = PetscOptionsGetInt(PETSC_NULL,tstr,&ThreadCoreAffinity[i],PETSC_NULL);CHKERRQ(ierr); 437ba61063dSBarry Smith ThreadCoreAffinity[i] = ThreadCoreAffinity[i]%N_CORES; /* check on the user */ 43851d315f7SKerry Stevens } 43951d315f7SKerry Stevens tstr[7] = '\0'; 44051d315f7SKerry Stevens } 441ba61063dSBarry Smith /* get the thread pool type */ 44251d315f7SKerry Stevens PetscInt ipool = 0; 44351d315f7SKerry Stevens ierr = PetscOptionsGetInt(PETSC_NULL,"-pool",&ipool,PETSC_NULL);CHKERRQ(ierr); 44451d315f7SKerry Stevens switch(ipool) { 44551d315f7SKerry Stevens case 1: 44651d315f7SKerry Stevens PetscThreadFunc = &PetscThreadFunc_Tree; 44751d315f7SKerry Stevens PetscThreadInitialize = &PetscThreadInitialize_Tree; 44851d315f7SKerry Stevens PetscThreadFinalize = &PetscThreadFinalize_Tree; 44951d315f7SKerry Stevens MainWait = &MainWait_Tree; 45051d315f7SKerry Stevens MainJob = &MainJob_Tree; 45151d315f7SKerry Stevens break; 45251d315f7SKerry Stevens case 2: 45351d315f7SKerry Stevens PetscThreadFunc = &PetscThreadFunc_Main; 45451d315f7SKerry Stevens PetscThreadInitialize = &PetscThreadInitialize_Main; 45551d315f7SKerry Stevens PetscThreadFinalize = &PetscThreadFinalize_Main; 45651d315f7SKerry Stevens MainWait = &MainWait_Main; 45751d315f7SKerry Stevens MainJob = &MainJob_Main; 45851d315f7SKerry Stevens break; 459*fc087633SBarry Smith #if defined(PETSC_HAVE_PTHREAD_BARRIER) 46051d315f7SKerry Stevens case 3: 461*fc087633SBarry Smith #else 462*fc087633SBarry Smith default: 463*fc087633SBarry Smith #endif 46451d315f7SKerry Stevens PetscThreadFunc = &PetscThreadFunc_Chain; 46551d315f7SKerry Stevens PetscThreadInitialize = &PetscThreadInitialize_Chain; 46651d315f7SKerry Stevens PetscThreadFinalize = &PetscThreadFinalize_Chain; 46751d315f7SKerry Stevens MainWait = &MainWait_Chain; 46851d315f7SKerry Stevens MainJob = &MainJob_Chain; 46951d315f7SKerry Stevens break; 470*fc087633SBarry Smith #if defined(PETSC_HAVE_PTHREAD_BARRIER) 47151d315f7SKerry Stevens default: 47251d315f7SKerry Stevens PetscThreadFunc = &PetscThreadFunc_True; 47351d315f7SKerry Stevens PetscThreadInitialize = &PetscThreadInitialize_True; 47451d315f7SKerry Stevens PetscThreadFinalize = &PetscThreadFinalize_True; 47551d315f7SKerry Stevens MainWait = &MainWait_True; 47651d315f7SKerry Stevens MainJob = &MainJob_True; 47751d315f7SKerry Stevens break; 478*fc087633SBarry Smith #endif 47951dcc849SKerry Stevens } 4800ca81413SKerry Stevens PetscThreadInitialize(PetscMaxThreads); 481*fc087633SBarry Smith } 482*fc087633SBarry Smith #endif 483*fc087633SBarry Smith 48451dcc849SKerry Stevens /* 485e5c89e4eSSatish Balay Print the PETSc version information 486e5c89e4eSSatish Balay */ 487e5c89e4eSSatish Balay ierr = PetscOptionsHasName(PETSC_NULL,"-v",&flg1);CHKERRQ(ierr); 488e5c89e4eSSatish Balay ierr = PetscOptionsHasName(PETSC_NULL,"-version",&flg2);CHKERRQ(ierr); 489e5c89e4eSSatish Balay ierr = PetscOptionsHasName(PETSC_NULL,"-help",&flg3);CHKERRQ(ierr); 490e5c89e4eSSatish Balay if (flg1 || flg2 || flg3){ 491e5c89e4eSSatish Balay 492e5c89e4eSSatish Balay /* 493e5c89e4eSSatish Balay Print "higher-level" package version message 494e5c89e4eSSatish Balay */ 495e5c89e4eSSatish Balay if (PetscExternalVersionFunction) { 496e5c89e4eSSatish Balay ierr = (*PetscExternalVersionFunction)(comm);CHKERRQ(ierr); 497e5c89e4eSSatish Balay } 498e5c89e4eSSatish Balay 499a523d312SBarry Smith ierr = PetscGetVersion(version,256);CHKERRQ(ierr); 500e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"--------------------------------------------\ 501e5c89e4eSSatish Balay ------------------------------\n");CHKERRQ(ierr); 502e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"%s\n",version);CHKERRQ(ierr); 503e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"%s",PETSC_AUTHOR_INFO);CHKERRQ(ierr); 504e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"See docs/changes/index.html for recent updates.\n");CHKERRQ(ierr); 50584e42920SBarry Smith ierr = (*PetscHelpPrintf)(comm,"See docs/faq.html for problems.\n");CHKERRQ(ierr); 506e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"See docs/manualpages/index.html for help. \n");CHKERRQ(ierr); 507e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"Libraries linked from %s\n",PETSC_LIB_DIR);CHKERRQ(ierr); 508e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"--------------------------------------------\ 509e5c89e4eSSatish Balay ------------------------------\n");CHKERRQ(ierr); 510e5c89e4eSSatish Balay } 511e5c89e4eSSatish Balay 512e5c89e4eSSatish Balay /* 513e5c89e4eSSatish Balay Print "higher-level" package help message 514e5c89e4eSSatish Balay */ 515e5c89e4eSSatish Balay if (flg3){ 516e5c89e4eSSatish Balay if (PetscExternalHelpFunction) { 517e5c89e4eSSatish Balay ierr = (*PetscExternalHelpFunction)(comm);CHKERRQ(ierr); 518e5c89e4eSSatish Balay } 519e5c89e4eSSatish Balay } 520e5c89e4eSSatish Balay 521e5c89e4eSSatish Balay /* 522e5c89e4eSSatish Balay Setup the error handling 523e5c89e4eSSatish Balay */ 52490d69ab7SBarry Smith flg1 = PETSC_FALSE; 525acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-on_error_abort",&flg1,PETSC_NULL);CHKERRQ(ierr); 526cb9801acSJed Brown if (flg1) { ierr = PetscPushErrorHandler(PetscAbortErrorHandler,0);CHKERRQ(ierr);} 52790d69ab7SBarry Smith flg1 = PETSC_FALSE; 528acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-on_error_mpiabort",&flg1,PETSC_NULL);CHKERRQ(ierr); 529cb9801acSJed Brown if (flg1) { ierr = PetscPushErrorHandler(PetscMPIAbortErrorHandler,0);CHKERRQ(ierr);} 53090d69ab7SBarry Smith flg1 = PETSC_FALSE; 531acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-mpi_return_on_error",&flg1,PETSC_NULL);CHKERRQ(ierr); 532e5c89e4eSSatish Balay if (flg1) { 533e5c89e4eSSatish Balay ierr = MPI_Errhandler_set(comm,MPI_ERRORS_RETURN);CHKERRQ(ierr); 534e5c89e4eSSatish Balay } 53590d69ab7SBarry Smith flg1 = PETSC_FALSE; 536acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-no_signal_handler",&flg1,PETSC_NULL);CHKERRQ(ierr); 537cb9801acSJed Brown if (!flg1) {ierr = PetscPushSignalHandler(PetscDefaultSignalHandler,(void*)0);CHKERRQ(ierr);} 53896cc47afSJed Brown flg1 = PETSC_FALSE; 539acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-fp_trap",&flg1,PETSC_NULL);CHKERRQ(ierr); 54096cc47afSJed Brown if (flg1) {ierr = PetscSetFPTrap(PETSC_FP_TRAP_ON);CHKERRQ(ierr);} 541e5c89e4eSSatish Balay 542e5c89e4eSSatish Balay /* 543e5c89e4eSSatish Balay Setup debugger information 544e5c89e4eSSatish Balay */ 545e5c89e4eSSatish Balay ierr = PetscSetDefaultDebugger();CHKERRQ(ierr); 546e5c89e4eSSatish Balay ierr = PetscOptionsGetString(PETSC_NULL,"-on_error_attach_debugger",string,64,&flg1);CHKERRQ(ierr); 547e5c89e4eSSatish Balay if (flg1) { 548e5c89e4eSSatish Balay MPI_Errhandler err_handler; 549e5c89e4eSSatish Balay 550e5c89e4eSSatish Balay ierr = PetscSetDebuggerFromString(string);CHKERRQ(ierr); 551e5c89e4eSSatish Balay ierr = MPI_Errhandler_create((MPI_Handler_function*)Petsc_MPI_DebuggerOnError,&err_handler);CHKERRQ(ierr); 552e5c89e4eSSatish Balay ierr = MPI_Errhandler_set(comm,err_handler);CHKERRQ(ierr); 553e5c89e4eSSatish Balay ierr = PetscPushErrorHandler(PetscAttachDebuggerErrorHandler,0);CHKERRQ(ierr); 554e5c89e4eSSatish Balay } 5555e96ac45SJed Brown ierr = PetscOptionsGetString(PETSC_NULL,"-debug_terminal",string,64,&flg1);CHKERRQ(ierr); 5565e96ac45SJed Brown if (flg1) { ierr = PetscSetDebugTerminal(string);CHKERRQ(ierr); } 557e5c89e4eSSatish Balay ierr = PetscOptionsGetString(PETSC_NULL,"-start_in_debugger",string,64,&flg1);CHKERRQ(ierr); 558e5c89e4eSSatish Balay ierr = PetscOptionsGetString(PETSC_NULL,"-stop_for_debugger",string,64,&flg2);CHKERRQ(ierr); 559e5c89e4eSSatish Balay if (flg1 || flg2) { 560e5c89e4eSSatish Balay PetscMPIInt size; 561e5c89e4eSSatish Balay PetscInt lsize,*nodes; 562e5c89e4eSSatish Balay MPI_Errhandler err_handler; 563e5c89e4eSSatish Balay /* 564e5c89e4eSSatish Balay we have to make sure that all processors have opened 565e5c89e4eSSatish Balay connections to all other processors, otherwise once the 566e5c89e4eSSatish Balay debugger has stated it is likely to receive a SIGUSR1 567e5c89e4eSSatish Balay and kill the program. 568e5c89e4eSSatish Balay */ 569e5c89e4eSSatish Balay ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); 570e5c89e4eSSatish Balay if (size > 2) { 571533163c2SBarry Smith PetscMPIInt dummy = 0; 572e5c89e4eSSatish Balay MPI_Status status; 573e5c89e4eSSatish Balay for (i=0; i<size; i++) { 574e5c89e4eSSatish Balay if (rank != i) { 575e5c89e4eSSatish Balay ierr = MPI_Send(&dummy,1,MPI_INT,i,109,PETSC_COMM_WORLD);CHKERRQ(ierr); 576e5c89e4eSSatish Balay } 577e5c89e4eSSatish Balay } 578e5c89e4eSSatish Balay for (i=0; i<size; i++) { 579e5c89e4eSSatish Balay if (rank != i) { 580e5c89e4eSSatish Balay ierr = MPI_Recv(&dummy,1,MPI_INT,i,109,PETSC_COMM_WORLD,&status);CHKERRQ(ierr); 581e5c89e4eSSatish Balay } 582e5c89e4eSSatish Balay } 583e5c89e4eSSatish Balay } 584e5c89e4eSSatish Balay /* check if this processor node should be in debugger */ 585e5c89e4eSSatish Balay ierr = PetscMalloc(size*sizeof(PetscInt),&nodes);CHKERRQ(ierr); 586e5c89e4eSSatish Balay lsize = size; 587e5c89e4eSSatish Balay ierr = PetscOptionsGetIntArray(PETSC_NULL,"-debugger_nodes",nodes,&lsize,&flag);CHKERRQ(ierr); 588e5c89e4eSSatish Balay if (flag) { 589e5c89e4eSSatish Balay for (i=0; i<lsize; i++) { 590e5c89e4eSSatish Balay if (nodes[i] == rank) { flag = PETSC_FALSE; break; } 591e5c89e4eSSatish Balay } 592e5c89e4eSSatish Balay } 593e5c89e4eSSatish Balay if (!flag) { 594e5c89e4eSSatish Balay ierr = PetscSetDebuggerFromString(string);CHKERRQ(ierr); 595e5c89e4eSSatish Balay ierr = PetscPushErrorHandler(PetscAbortErrorHandler,0);CHKERRQ(ierr); 596e5c89e4eSSatish Balay if (flg1) { 597e5c89e4eSSatish Balay ierr = PetscAttachDebugger();CHKERRQ(ierr); 598e5c89e4eSSatish Balay } else { 599e5c89e4eSSatish Balay ierr = PetscStopForDebugger();CHKERRQ(ierr); 600e5c89e4eSSatish Balay } 601e5c89e4eSSatish Balay ierr = MPI_Errhandler_create((MPI_Handler_function*)Petsc_MPI_AbortOnError,&err_handler);CHKERRQ(ierr); 602e5c89e4eSSatish Balay ierr = MPI_Errhandler_set(comm,err_handler);CHKERRQ(ierr); 603e5c89e4eSSatish Balay } 604e5c89e4eSSatish Balay ierr = PetscFree(nodes);CHKERRQ(ierr); 605e5c89e4eSSatish Balay } 606e5c89e4eSSatish Balay 607e5c89e4eSSatish Balay ierr = PetscOptionsGetString(PETSC_NULL,"-on_error_emacs",emacsmachinename,128,&flg1);CHKERRQ(ierr); 608cb9801acSJed Brown if (flg1 && !rank) {ierr = PetscPushErrorHandler(PetscEmacsClientErrorHandler,emacsmachinename);CHKERRQ(ierr);} 609e5c89e4eSSatish Balay 61093ba235fSBarry Smith #if defined(PETSC_USE_SOCKET_VIEWER) 61122b84c2fSbcordonn /* 61222b84c2fSbcordonn Activates new sockets for zope if needed 61322b84c2fSbcordonn */ 61484ab5442Sbcordonn ierr = PetscOptionsHasName(PETSC_NULL,"-zope", &flgz);CHKERRQ(ierr); 615d8c6e182Sbcordonn ierr = PetscOptionsHasName(PETSC_NULL,"-nostdout", &flgzout);CHKERRQ(ierr); 6166dc8fec2Sbcordonn if (flgz){ 61722b84c2fSbcordonn int sockfd; 618f1384234SBarry Smith char hostname[256]; 61922b84c2fSbcordonn char username[256]; 6206dc8fec2Sbcordonn int remoteport = 9999; 6219c4c166aSBarry Smith 62284ab5442Sbcordonn ierr = PetscOptionsGetString(PETSC_NULL, "-zope", hostname, 256, &flgz);CHKERRQ(ierr); 62384ab5442Sbcordonn if (!hostname[0]){ 6249c4c166aSBarry Smith ierr = PetscGetHostName(hostname,256);CHKERRQ(ierr); 6259c4c166aSBarry Smith } 62622b84c2fSbcordonn ierr = PetscOpenSocket(hostname, remoteport, &sockfd);CHKERRQ(ierr); 6279c4c166aSBarry Smith ierr = PetscGetUserName(username, 256);CHKERRQ(ierr); 62822b84c2fSbcordonn PETSC_ZOPEFD = fdopen(sockfd, "w"); 62922b84c2fSbcordonn if (flgzout){ 63022b84c2fSbcordonn PETSC_STDOUT = PETSC_ZOPEFD; 631606f100bSbcordonn fprintf(PETSC_STDOUT, "<<<user>>> %s\n",username); 6326dc8fec2Sbcordonn fprintf(PETSC_STDOUT, "<<<start>>>"); 6339c4c166aSBarry Smith } else { 634d8c6e182Sbcordonn fprintf(PETSC_ZOPEFD, "<<<user>>> %s\n",username); 635d8c6e182Sbcordonn fprintf(PETSC_ZOPEFD, "<<<start>>>"); 6369c4c166aSBarry Smith } 6379c4c166aSBarry Smith } 63893ba235fSBarry Smith #endif 639ffc871a5SBarry Smith #if defined(PETSC_USE_SERVER) 640ffc871a5SBarry Smith ierr = PetscOptionsHasName(PETSC_NULL,"-server", &flgz);CHKERRQ(ierr); 641ffc871a5SBarry Smith if (flgz){ 642ffc871a5SBarry Smith PetscInt port = PETSC_DECIDE; 643ffc871a5SBarry Smith ierr = PetscOptionsGetInt(PETSC_NULL,"-server",&port,PETSC_NULL);CHKERRQ(ierr); 644ffc871a5SBarry Smith ierr = PetscWebServe(PETSC_COMM_WORLD,(int)port);CHKERRQ(ierr); 645ffc871a5SBarry Smith } 646ffc871a5SBarry Smith #endif 6476dc8fec2Sbcordonn 648e5c89e4eSSatish Balay /* 649e5c89e4eSSatish Balay Setup profiling and logging 650e5c89e4eSSatish Balay */ 6516cf91177SBarry Smith #if defined (PETSC_USE_INFO) 6528bb29257SSatish Balay { 653e5c89e4eSSatish Balay char logname[PETSC_MAX_PATH_LEN]; logname[0] = 0; 6546cf91177SBarry Smith ierr = PetscOptionsGetString(PETSC_NULL,"-info",logname,250,&flg1);CHKERRQ(ierr); 6558bb29257SSatish Balay if (flg1 && logname[0]) { 656fcc2139eSBarry Smith ierr = PetscInfoAllow(PETSC_TRUE,logname);CHKERRQ(ierr); 6578bb29257SSatish Balay } else if (flg1) { 658fcc2139eSBarry Smith ierr = PetscInfoAllow(PETSC_TRUE,PETSC_NULL);CHKERRQ(ierr); 659e5c89e4eSSatish Balay } 660e5c89e4eSSatish Balay } 661865f6aa8SSatish Balay #endif 662865f6aa8SSatish Balay #if defined(PETSC_USE_LOG) 663865f6aa8SSatish Balay mname[0] = 0; 664f3dea69dSBarry Smith ierr = PetscOptionsGetString(PETSC_NULL,"-history",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); 665865f6aa8SSatish Balay if (flg1) { 666865f6aa8SSatish Balay if (mname[0]) { 667f3dea69dSBarry Smith ierr = PetscOpenHistoryFile(mname,&petsc_history);CHKERRQ(ierr); 668865f6aa8SSatish Balay } else { 669f3dea69dSBarry Smith ierr = PetscOpenHistoryFile(0,&petsc_history);CHKERRQ(ierr); 670865f6aa8SSatish Balay } 671865f6aa8SSatish Balay } 672e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MPE) 67390d69ab7SBarry Smith flg1 = PETSC_FALSE; 674fcfd50ebSBarry Smith ierr = PetscOptionsHasName(PETSC_NULL,"-log_mpe",&flg1);CHKERRQ(ierr); 675e5c89e4eSSatish Balay if (flg1) PetscLogMPEBegin(); 676e5c89e4eSSatish Balay #endif 67790d69ab7SBarry Smith flg1 = PETSC_FALSE; 67890d69ab7SBarry Smith flg2 = PETSC_FALSE; 67990d69ab7SBarry Smith flg3 = PETSC_FALSE; 680acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-log_all",&flg1,PETSC_NULL);CHKERRQ(ierr); 681acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-log",&flg2,PETSC_NULL);CHKERRQ(ierr); 682d44e083bSSatish Balay ierr = PetscOptionsHasName(PETSC_NULL,"-log_summary",&flg3);CHKERRQ(ierr); 6839f7b6320SBarry Smith ierr = PetscOptionsHasName(PETSC_NULL,"-log_summary_python",&flg4);CHKERRQ(ierr); 684e5c89e4eSSatish Balay if (flg1) { ierr = PetscLogAllBegin();CHKERRQ(ierr); } 6859f7b6320SBarry Smith else if (flg2 || flg3 || flg4) { ierr = PetscLogBegin();CHKERRQ(ierr);} 686e5c89e4eSSatish Balay 687e5c89e4eSSatish Balay ierr = PetscOptionsGetString(PETSC_NULL,"-log_trace",mname,250,&flg1);CHKERRQ(ierr); 688e5c89e4eSSatish Balay if (flg1) { 689e5c89e4eSSatish Balay char name[PETSC_MAX_PATH_LEN],fname[PETSC_MAX_PATH_LEN]; 690e5c89e4eSSatish Balay FILE *file; 691e5c89e4eSSatish Balay if (mname[0]) { 692e5c89e4eSSatish Balay sprintf(name,"%s.%d",mname,rank); 693e5c89e4eSSatish Balay ierr = PetscFixFilename(name,fname);CHKERRQ(ierr); 694e5c89e4eSSatish Balay file = fopen(fname,"w"); 695f3dea69dSBarry Smith if (!file) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open trace file: %s",fname); 696e5c89e4eSSatish Balay } else { 697da9f1d6bSBarry Smith file = PETSC_STDOUT; 698e5c89e4eSSatish Balay } 699e5c89e4eSSatish Balay ierr = PetscLogTraceBegin(file);CHKERRQ(ierr); 700e5c89e4eSSatish Balay } 701e5c89e4eSSatish Balay #endif 702e5c89e4eSSatish Balay 703e5c89e4eSSatish Balay /* 704e5c89e4eSSatish Balay Setup building of stack frames for all function calls 705e5c89e4eSSatish Balay */ 70663d6bff0SBarry Smith #if defined(PETSC_USE_DEBUG) && !defined(PETSC_USE_PTHREAD) 707e5c89e4eSSatish Balay ierr = PetscStackCreate();CHKERRQ(ierr); 708e5c89e4eSSatish Balay #endif 709e5c89e4eSSatish Balay 710acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-options_gui",&PetscOptionsPublish,PETSC_NULL);CHKERRQ(ierr); 711e5c89e4eSSatish Balay 712e5c89e4eSSatish Balay /* 713e5c89e4eSSatish Balay Print basic help message 714e5c89e4eSSatish Balay */ 715e5c89e4eSSatish Balay ierr = PetscOptionsHasName(PETSC_NULL,"-help",&flg1);CHKERRQ(ierr); 716e5c89e4eSSatish Balay if (flg1) { 717e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"Options for all PETSc programs:\n");CHKERRQ(ierr); 718301d30feSBarry Smith ierr = (*PetscHelpPrintf)(comm," -help: prints help method for each option\n");CHKERRQ(ierr); 719301d30feSBarry Smith ierr = (*PetscHelpPrintf)(comm," -on_error_abort: cause an abort when an error is detected. Useful \n ");CHKERRQ(ierr); 720301d30feSBarry Smith ierr = (*PetscHelpPrintf)(comm," only when run in the debugger\n");CHKERRQ(ierr); 721e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -on_error_attach_debugger [gdb,dbx,xxgdb,ups,noxterm]\n");CHKERRQ(ierr); 722e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," start the debugger in new xterm\n");CHKERRQ(ierr); 723e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," unless noxterm is given\n");CHKERRQ(ierr); 724e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -start_in_debugger [gdb,dbx,xxgdb,ups,noxterm]\n");CHKERRQ(ierr); 725e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," start all processes in the debugger\n");CHKERRQ(ierr); 726e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -on_error_emacs <machinename>\n");CHKERRQ(ierr); 727e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," emacs jumps to error file\n");CHKERRQ(ierr); 728e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -debugger_nodes [n1,n2,..] Nodes to start in debugger\n");CHKERRQ(ierr); 729e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -debugger_pause [m] : delay (in seconds) to attach debugger\n");CHKERRQ(ierr); 730e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -stop_for_debugger : prints message on how to attach debugger manually\n");CHKERRQ(ierr); 731e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," waits the delay for you to attach\n");CHKERRQ(ierr); 732e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -display display: Location where graphics and debuggers are displayed\n");CHKERRQ(ierr); 733e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -no_signal_handler: do not trap error signals\n");CHKERRQ(ierr); 734e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -mpi_return_on_error: MPI returns error code, rather than abort on internal error\n");CHKERRQ(ierr); 735e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -fp_trap: stop on floating point exceptions\n");CHKERRQ(ierr); 736e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," note on IBM RS6000 this slows run greatly\n");CHKERRQ(ierr); 737e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -malloc_dump <optional filename>: dump list of unfreed memory at conclusion\n");CHKERRQ(ierr); 738e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -malloc: use our error checking malloc\n");CHKERRQ(ierr); 739e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -malloc no: don't use error checking malloc\n");CHKERRQ(ierr); 7404161f2a3SBarry Smith ierr = (*PetscHelpPrintf)(comm," -malloc_info: prints total memory usage\n");CHKERRQ(ierr); 7414161f2a3SBarry Smith ierr = (*PetscHelpPrintf)(comm," -malloc_log: keeps log of all memory allocations\n");CHKERRQ(ierr); 742e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -malloc_debug: enables extended checking for memory corruption\n");CHKERRQ(ierr); 743e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -options_table: dump list of options inputted\n");CHKERRQ(ierr); 744e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -options_left: dump list of unused options\n");CHKERRQ(ierr); 745e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -options_left no: don't dump list of unused options\n");CHKERRQ(ierr); 746e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -tmp tmpdir: alternative /tmp directory\n");CHKERRQ(ierr); 747e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -shared_tmp: tmp directory is shared by all processors\n");CHKERRQ(ierr); 748a8c7a070SBarry Smith ierr = (*PetscHelpPrintf)(comm," -not_shared_tmp: each processor has separate tmp directory\n");CHKERRQ(ierr); 749e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -memory_info: print memory usage at end of run\n");CHKERRQ(ierr); 750e5c89e4eSSatish Balay #if defined(PETSC_USE_LOG) 751e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -get_total_flops: total flops over all processors\n");CHKERRQ(ierr); 752e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -log[_all _summary]: logging objects and events\n");CHKERRQ(ierr); 753e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -log_trace [filename]: prints trace of all PETSc calls\n");CHKERRQ(ierr); 754e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MPE) 755e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -log_mpe: Also create logfile viewable through upshot\n");CHKERRQ(ierr); 756e5c89e4eSSatish Balay #endif 7576cf91177SBarry Smith ierr = (*PetscHelpPrintf)(comm," -info <optional filename>: print informative messages about the calculations\n");CHKERRQ(ierr); 758e5c89e4eSSatish Balay #endif 759e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -v: prints PETSc version number and release date\n");CHKERRQ(ierr); 760e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -options_file <file>: reads options from file\n");CHKERRQ(ierr); 761e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -petsc_sleep n: sleeps n seconds before running program\n");CHKERRQ(ierr); 762e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"-----------------------------------------------\n");CHKERRQ(ierr); 763e5c89e4eSSatish Balay } 764e5c89e4eSSatish Balay 765a6d0e24fSJed Brown ierr = PetscOptionsGetReal(PETSC_NULL,"-petsc_sleep",&si,&flg1);CHKERRQ(ierr); 766e5c89e4eSSatish Balay if (flg1) { 767e5c89e4eSSatish Balay ierr = PetscSleep(si);CHKERRQ(ierr); 768e5c89e4eSSatish Balay } 769e5c89e4eSSatish Balay 7706cf91177SBarry Smith ierr = PetscOptionsGetString(PETSC_NULL,"-info_exclude",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); 771e5c89e4eSSatish Balay ierr = PetscStrstr(mname,"null",&f);CHKERRQ(ierr); 772e5c89e4eSSatish Balay if (f) { 7736cf91177SBarry Smith ierr = PetscInfoDeactivateClass(PETSC_NULL);CHKERRQ(ierr); 774e5c89e4eSSatish Balay } 775827f890bSBarry Smith 7768154be41SBarry Smith #if defined(PETSC_HAVE_CUSP) 777c97f9302SBarry Smith ierr = PetscOptionsHasName(PETSC_NULL,"-log_summary",&flg3);CHKERRQ(ierr); 77873113deaSBarry Smith if (flg3) flg1 = PETSC_TRUE; 77973113deaSBarry Smith else flg1 = PETSC_FALSE; 7808154be41SBarry Smith ierr = PetscOptionsGetBool(PETSC_NULL,"-cusp_synchronize",&flg1,PETSC_NULL);CHKERRQ(ierr); 7818154be41SBarry Smith if (flg1) synchronizeCUSP = PETSC_TRUE; 782bab1f7e6SVictor Minden #endif 783192daf7cSBarry Smith 784e5c89e4eSSatish Balay PetscFunctionReturn(0); 785e5c89e4eSSatish Balay } 786df413903SBarry Smith 787ba61063dSBarry Smith #if defined(PETSC_USE_PTHREAD_CLASSES) 788ba61063dSBarry Smith 78951d315f7SKerry Stevens /**** 'Tree' Thread Pool Functions ****/ 79051d315f7SKerry Stevens void* PetscThreadFunc_Tree(void* arg) { 79151d315f7SKerry Stevens PetscErrorCode iterr; 79251d315f7SKerry Stevens int icorr,ierr; 79351d315f7SKerry Stevens int* pId = (int*)arg; 79451d315f7SKerry Stevens int ThreadId = *pId,Mary = 2,i,SubWorker; 79551d315f7SKerry Stevens PetscBool PeeOn; 79651d315f7SKerry Stevens cpu_set_t mset; 79751d315f7SKerry Stevens 79851d315f7SKerry Stevens icorr = ThreadCoreAffinity[ThreadId]; 79951d315f7SKerry Stevens CPU_ZERO(&mset); 80051d315f7SKerry Stevens CPU_SET(icorr,&mset); 80151d315f7SKerry Stevens sched_setaffinity(0,sizeof(cpu_set_t),&mset); 80251d315f7SKerry Stevens 80351d315f7SKerry Stevens if((Mary*ThreadId+1)>(PetscMaxThreads-1)) { 80451d315f7SKerry Stevens PeeOn = PETSC_TRUE; 80551d315f7SKerry Stevens } 80651d315f7SKerry Stevens else { 80751d315f7SKerry Stevens PeeOn = PETSC_FALSE; 80851d315f7SKerry Stevens } 80951d315f7SKerry Stevens if(PeeOn==PETSC_FALSE) { 810ba61063dSBarry Smith /* check your subordinates, wait for them to be ready */ 81151d315f7SKerry Stevens for(i=1;i<=Mary;i++) { 81251d315f7SKerry Stevens SubWorker = Mary*ThreadId+i; 81351d315f7SKerry Stevens if(SubWorker<PetscMaxThreads) { 81451d315f7SKerry Stevens ierr = pthread_mutex_lock(job_tree.mutexarray[SubWorker]); 81551d315f7SKerry Stevens while(*(job_tree.arrThreadReady[SubWorker])==PETSC_FALSE) { 816ba61063dSBarry Smith /* upon entry, automically releases the lock and blocks 817ba61063dSBarry Smith upon return, has the lock */ 81851d315f7SKerry Stevens ierr = pthread_cond_wait(job_tree.cond1array[SubWorker],job_tree.mutexarray[SubWorker]); 81951d315f7SKerry Stevens } 82051d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_tree.mutexarray[SubWorker]); 82151d315f7SKerry Stevens } 82251d315f7SKerry Stevens } 823ba61063dSBarry Smith /* your subordinates are now ready */ 82451d315f7SKerry Stevens } 82551d315f7SKerry Stevens ierr = pthread_mutex_lock(job_tree.mutexarray[ThreadId]); 826ba61063dSBarry Smith /* update your ready status */ 82751d315f7SKerry Stevens *(job_tree.arrThreadReady[ThreadId]) = PETSC_TRUE; 82851d315f7SKerry Stevens if(ThreadId==0) { 82951d315f7SKerry Stevens job_tree.eJobStat = JobCompleted; 830ba61063dSBarry Smith /* ignal main */ 83151d315f7SKerry Stevens ierr = pthread_cond_signal(&main_cond); 83251d315f7SKerry Stevens } 83351d315f7SKerry Stevens else { 834ba61063dSBarry Smith /* tell your boss that you're ready to work */ 83551d315f7SKerry Stevens ierr = pthread_cond_signal(job_tree.cond1array[ThreadId]); 83651d315f7SKerry Stevens } 837ba61063dSBarry Smith /* the while loop needs to have an exit 838ba61063dSBarry Smith the 'main' thread can terminate all the threads by performing a broadcast 839ba61063dSBarry Smith and calling FuncFinish */ 84051d315f7SKerry Stevens while(PetscThreadGo) { 841ba61063dSBarry Smith /*need to check the condition to ensure we don't have to wait 842ba61063dSBarry Smith waiting when you don't have to causes problems 843ba61063dSBarry Smith also need to check the condition to ensure proper handling of spurious wakeups */ 84451d315f7SKerry Stevens while(*(job_tree.arrThreadReady[ThreadId])==PETSC_TRUE) { 845ba61063dSBarry Smith /* upon entry, automically releases the lock and blocks 846ba61063dSBarry Smith upon return, has the lock */ 84751d315f7SKerry Stevens ierr = pthread_cond_wait(job_tree.cond2array[ThreadId],job_tree.mutexarray[ThreadId]); 84851d315f7SKerry Stevens *(job_tree.arrThreadStarted[ThreadId]) = PETSC_TRUE; 84951d315f7SKerry Stevens *(job_tree.arrThreadReady[ThreadId]) = PETSC_FALSE; 85051d315f7SKerry Stevens } 85151d315f7SKerry Stevens if(ThreadId==0) { 85251d315f7SKerry Stevens job_tree.startJob = PETSC_FALSE; 85351d315f7SKerry Stevens job_tree.eJobStat = ThreadsWorking; 85451d315f7SKerry Stevens } 85551d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_tree.mutexarray[ThreadId]); 85651d315f7SKerry Stevens if(PeeOn==PETSC_FALSE) { 857ba61063dSBarry Smith /* tell your subordinates it's time to get to work */ 85851d315f7SKerry Stevens for(i=1; i<=Mary; i++) { 85951d315f7SKerry Stevens SubWorker = Mary*ThreadId+i; 86051d315f7SKerry Stevens if(SubWorker<PetscMaxThreads) { 86151d315f7SKerry Stevens ierr = pthread_cond_signal(job_tree.cond2array[SubWorker]); 86251d315f7SKerry Stevens } 86351d315f7SKerry Stevens } 86451d315f7SKerry Stevens } 865ba61063dSBarry Smith /* do your job */ 86651d315f7SKerry Stevens if(job_tree.pdata==NULL) { 86751d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_tree.pfunc(job_tree.pdata); 86851d315f7SKerry Stevens } 86951d315f7SKerry Stevens else { 87051d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_tree.pfunc(job_tree.pdata[ThreadId]); 87151d315f7SKerry Stevens } 87251d315f7SKerry Stevens if(iterr!=0) { 87351d315f7SKerry Stevens ithreaderr = 1; 87451d315f7SKerry Stevens } 87551d315f7SKerry Stevens if(PetscThreadGo) { 876ba61063dSBarry Smith /* reset job, get ready for more */ 87751d315f7SKerry Stevens if(PeeOn==PETSC_FALSE) { 878ba61063dSBarry Smith /* check your subordinates, waiting for them to be ready 879ba61063dSBarry Smith how do you know for a fact that a given subordinate has actually started? */ 88051d315f7SKerry Stevens for(i=1;i<=Mary;i++) { 88151d315f7SKerry Stevens SubWorker = Mary*ThreadId+i; 88251d315f7SKerry Stevens if(SubWorker<PetscMaxThreads) { 88351d315f7SKerry Stevens ierr = pthread_mutex_lock(job_tree.mutexarray[SubWorker]); 88451d315f7SKerry Stevens while(*(job_tree.arrThreadReady[SubWorker])==PETSC_FALSE||*(job_tree.arrThreadStarted[SubWorker])==PETSC_FALSE) { 885ba61063dSBarry Smith /* upon entry, automically releases the lock and blocks 886ba61063dSBarry Smith upon return, has the lock */ 88751d315f7SKerry Stevens ierr = pthread_cond_wait(job_tree.cond1array[SubWorker],job_tree.mutexarray[SubWorker]); 88851d315f7SKerry Stevens } 88951d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_tree.mutexarray[SubWorker]); 89051d315f7SKerry Stevens } 89151d315f7SKerry Stevens } 892ba61063dSBarry Smith /* your subordinates are now ready */ 89351d315f7SKerry Stevens } 89451d315f7SKerry Stevens ierr = pthread_mutex_lock(job_tree.mutexarray[ThreadId]); 89551d315f7SKerry Stevens *(job_tree.arrThreadReady[ThreadId]) = PETSC_TRUE; 89651d315f7SKerry Stevens if(ThreadId==0) { 897ba61063dSBarry Smith job_tree.eJobStat = JobCompleted; /* oot thread: last thread to complete, guaranteed! */ 898ba61063dSBarry Smith /* root thread signals 'main' */ 89951d315f7SKerry Stevens ierr = pthread_cond_signal(&main_cond); 90051d315f7SKerry Stevens } 90151d315f7SKerry Stevens else { 902ba61063dSBarry Smith /* signal your boss before you go to sleep */ 90351d315f7SKerry Stevens ierr = pthread_cond_signal(job_tree.cond1array[ThreadId]); 90451d315f7SKerry Stevens } 90551d315f7SKerry Stevens } 90651d315f7SKerry Stevens } 90751d315f7SKerry Stevens return NULL; 90851d315f7SKerry Stevens } 90951d315f7SKerry Stevens 91051d315f7SKerry Stevens #undef __FUNCT__ 91151d315f7SKerry Stevens #define __FUNCT__ "PetscThreadInitialize_Tree" 91251d315f7SKerry Stevens void* PetscThreadInitialize_Tree(PetscInt N) { 91351d315f7SKerry Stevens PetscInt i,ierr; 91451d315f7SKerry Stevens int status; 91551d315f7SKerry Stevens 91651d315f7SKerry Stevens if(PetscUseThreadPool) { 91751d315f7SKerry Stevens size_t Val1 = (size_t)CACHE_LINE_SIZE; 91851d315f7SKerry Stevens size_t Val2 = (size_t)PetscMaxThreads*CACHE_LINE_SIZE; 91951d315f7SKerry Stevens arrmutex = (char*)memalign(Val1,Val2); 92051d315f7SKerry Stevens arrcond1 = (char*)memalign(Val1,Val2); 92151d315f7SKerry Stevens arrcond2 = (char*)memalign(Val1,Val2); 92251d315f7SKerry Stevens arrstart = (char*)memalign(Val1,Val2); 92351d315f7SKerry Stevens arrready = (char*)memalign(Val1,Val2); 92451d315f7SKerry Stevens job_tree.mutexarray = (pthread_mutex_t**)malloc(PetscMaxThreads*sizeof(pthread_mutex_t*)); 92551d315f7SKerry Stevens job_tree.cond1array = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*)); 92651d315f7SKerry Stevens job_tree.cond2array = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*)); 92751d315f7SKerry Stevens job_tree.arrThreadStarted = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*)); 92851d315f7SKerry Stevens job_tree.arrThreadReady = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*)); 929ba61063dSBarry Smith /* initialize job structure */ 93051d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 93151d315f7SKerry Stevens job_tree.mutexarray[i] = (pthread_mutex_t*)(arrmutex+CACHE_LINE_SIZE*i); 93251d315f7SKerry Stevens job_tree.cond1array[i] = (pthread_cond_t*)(arrcond1+CACHE_LINE_SIZE*i); 93351d315f7SKerry Stevens job_tree.cond2array[i] = (pthread_cond_t*)(arrcond2+CACHE_LINE_SIZE*i); 93451d315f7SKerry Stevens job_tree.arrThreadStarted[i] = (PetscBool*)(arrstart+CACHE_LINE_SIZE*i); 93551d315f7SKerry Stevens job_tree.arrThreadReady[i] = (PetscBool*)(arrready+CACHE_LINE_SIZE*i); 93651d315f7SKerry Stevens } 93751d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 93851d315f7SKerry Stevens ierr = pthread_mutex_init(job_tree.mutexarray[i],NULL); 93951d315f7SKerry Stevens ierr = pthread_cond_init(job_tree.cond1array[i],NULL); 94051d315f7SKerry Stevens ierr = pthread_cond_init(job_tree.cond2array[i],NULL); 94151d315f7SKerry Stevens *(job_tree.arrThreadStarted[i]) = PETSC_FALSE; 94251d315f7SKerry Stevens *(job_tree.arrThreadReady[i]) = PETSC_FALSE; 94351d315f7SKerry Stevens } 94451d315f7SKerry Stevens job_tree.pfunc = NULL; 94551d315f7SKerry Stevens job_tree.pdata = (void**)malloc(N*sizeof(void*)); 94651d315f7SKerry Stevens job_tree.startJob = PETSC_FALSE; 94751d315f7SKerry Stevens job_tree.eJobStat = JobInitiated; 94851d315f7SKerry Stevens pVal = (int*)malloc(N*sizeof(int)); 949ba61063dSBarry Smith /* allocate memory in the heap for the thread structure */ 95051d315f7SKerry Stevens PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t)); 951ba61063dSBarry Smith /* create threads */ 95251d315f7SKerry Stevens for(i=0; i<N; i++) { 95351d315f7SKerry Stevens pVal[i] = i; 95451d315f7SKerry Stevens status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]); 955ba61063dSBarry Smith /* should check status */ 95651d315f7SKerry Stevens } 95751d315f7SKerry Stevens } 95851d315f7SKerry Stevens return NULL; 95951d315f7SKerry Stevens } 96051d315f7SKerry Stevens 96151d315f7SKerry Stevens #undef __FUNCT__ 96251d315f7SKerry Stevens #define __FUNCT__ "PetscThreadFinalize_Tree" 96351d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Tree() { 96451d315f7SKerry Stevens int i,ierr; 96551d315f7SKerry Stevens void* jstatus; 96651d315f7SKerry Stevens 96751d315f7SKerry Stevens PetscFunctionBegin; 96851d315f7SKerry Stevens 96951d315f7SKerry Stevens if(PetscUseThreadPool) { 970ba61063dSBarry Smith MainJob(FuncFinish,NULL,PetscMaxThreads); /* set up job and broadcast work */ 971ba61063dSBarry Smith /* join the threads */ 97251d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 97351d315f7SKerry Stevens ierr = pthread_join(PetscThreadPoint[i],&jstatus); 974ba61063dSBarry Smith /* do error checking*/ 97551d315f7SKerry Stevens } 97651d315f7SKerry Stevens free(PetscThreadPoint); 97751d315f7SKerry Stevens free(arrmutex); 97851d315f7SKerry Stevens free(arrcond1); 97951d315f7SKerry Stevens free(arrcond2); 98051d315f7SKerry Stevens free(arrstart); 98151d315f7SKerry Stevens free(arrready); 98251d315f7SKerry Stevens free(job_tree.pdata); 98351d315f7SKerry Stevens free(pVal); 98451d315f7SKerry Stevens } 98551d315f7SKerry Stevens else { 98651d315f7SKerry Stevens } 98751d315f7SKerry Stevens PetscFunctionReturn(0); 98851d315f7SKerry Stevens } 98951d315f7SKerry Stevens 99051d315f7SKerry Stevens #undef __FUNCT__ 99151d315f7SKerry Stevens #define __FUNCT__ "MainWait_Tree" 99251d315f7SKerry Stevens void MainWait_Tree() { 99351d315f7SKerry Stevens int ierr; 99451d315f7SKerry Stevens ierr = pthread_mutex_lock(job_tree.mutexarray[0]); 99551d315f7SKerry Stevens while(job_tree.eJobStat<JobCompleted||job_tree.startJob==PETSC_TRUE) { 99651d315f7SKerry Stevens ierr = pthread_cond_wait(&main_cond,job_tree.mutexarray[0]); 99751d315f7SKerry Stevens } 99851d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_tree.mutexarray[0]); 99951d315f7SKerry Stevens } 100051d315f7SKerry Stevens 100151d315f7SKerry Stevens #undef __FUNCT__ 100251d315f7SKerry Stevens #define __FUNCT__ "MainJob_Tree" 100351d315f7SKerry Stevens PetscErrorCode MainJob_Tree(void* (*pFunc)(void*),void** data,PetscInt n) { 100451d315f7SKerry Stevens int i,ierr; 100551d315f7SKerry Stevens PetscErrorCode ijoberr = 0; 100651d315f7SKerry Stevens if(PetscUseThreadPool) { 100751d315f7SKerry Stevens MainWait(); 100851d315f7SKerry Stevens job_tree.pfunc = pFunc; 100951d315f7SKerry Stevens job_tree.pdata = data; 101051d315f7SKerry Stevens job_tree.startJob = PETSC_TRUE; 101151d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 101251d315f7SKerry Stevens *(job_tree.arrThreadStarted[i]) = PETSC_FALSE; 101351d315f7SKerry Stevens } 101451d315f7SKerry Stevens job_tree.eJobStat = JobInitiated; 101551d315f7SKerry Stevens ierr = pthread_cond_signal(job_tree.cond2array[0]); 101651d315f7SKerry Stevens if(pFunc!=FuncFinish) { 1017ba61063dSBarry Smith MainWait(); /* why wait after? guarantees that job gets done before proceeding with result collection (if any) */ 101851d315f7SKerry Stevens } 101951d315f7SKerry Stevens } 102051d315f7SKerry Stevens else { 102151d315f7SKerry Stevens pthread_t* apThread = (pthread_t*)malloc(n*sizeof(pthread_t)); 102251d315f7SKerry Stevens PetscThreadRun(MPI_COMM_WORLD,pFunc,n,apThread,data); 1023ba61063dSBarry Smith PetscThreadStop(MPI_COMM_WORLD,n,apThread); /* ensures that all threads are finished with the job */ 102451d315f7SKerry Stevens free(apThread); 102551d315f7SKerry Stevens } 102651d315f7SKerry Stevens if(ithreaderr) { 102751d315f7SKerry Stevens ijoberr = ithreaderr; 102851d315f7SKerry Stevens } 102951d315f7SKerry Stevens return ijoberr; 103051d315f7SKerry Stevens } 103151d315f7SKerry Stevens /**** ****/ 103251d315f7SKerry Stevens 103351d315f7SKerry Stevens /**** 'Main' Thread Pool Functions ****/ 103451d315f7SKerry Stevens void* PetscThreadFunc_Main(void* arg) { 103551d315f7SKerry Stevens PetscErrorCode iterr; 103651d315f7SKerry Stevens int icorr,ierr; 103751d315f7SKerry Stevens int* pId = (int*)arg; 103851d315f7SKerry Stevens int ThreadId = *pId; 103951d315f7SKerry Stevens cpu_set_t mset; 104051d315f7SKerry Stevens 104151d315f7SKerry Stevens icorr = ThreadCoreAffinity[ThreadId]; 104251d315f7SKerry Stevens CPU_ZERO(&mset); 104351d315f7SKerry Stevens CPU_SET(icorr,&mset); 104451d315f7SKerry Stevens sched_setaffinity(0,sizeof(cpu_set_t),&mset); 104551d315f7SKerry Stevens 104651d315f7SKerry Stevens ierr = pthread_mutex_lock(job_main.mutexarray[ThreadId]); 1047ba61063dSBarry Smith /* update your ready status */ 104851d315f7SKerry Stevens *(job_main.arrThreadReady[ThreadId]) = PETSC_TRUE; 1049ba61063dSBarry Smith /* tell the BOSS that you're ready to work before you go to sleep */ 105051d315f7SKerry Stevens ierr = pthread_cond_signal(job_main.cond1array[ThreadId]); 105151d315f7SKerry Stevens 1052ba61063dSBarry Smith /* the while loop needs to have an exit 1053ba61063dSBarry Smith the 'main' thread can terminate all the threads by performing a broadcast 1054ba61063dSBarry Smith and calling FuncFinish */ 105551d315f7SKerry Stevens while(PetscThreadGo) { 1056ba61063dSBarry Smith /* need to check the condition to ensure we don't have to wait 1057ba61063dSBarry Smith waiting when you don't have to causes problems 1058ba61063dSBarry Smith also need to check the condition to ensure proper handling of spurious wakeups */ 105951d315f7SKerry Stevens while(*(job_main.arrThreadReady[ThreadId])==PETSC_TRUE) { 1060ba61063dSBarry Smith /* upon entry, atomically releases the lock and blocks 1061ba61063dSBarry Smith upon return, has the lock */ 106251d315f7SKerry Stevens ierr = pthread_cond_wait(job_main.cond2array[ThreadId],job_main.mutexarray[ThreadId]); 1063ba61063dSBarry Smith /* (job_main.arrThreadReady[ThreadId]) = PETSC_FALSE; */ 106451d315f7SKerry Stevens } 106551d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_main.mutexarray[ThreadId]); 106651d315f7SKerry Stevens if(job_main.pdata==NULL) { 106751d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_main.pfunc(job_main.pdata); 106851d315f7SKerry Stevens } 106951d315f7SKerry Stevens else { 107051d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_main.pfunc(job_main.pdata[ThreadId]); 107151d315f7SKerry Stevens } 107251d315f7SKerry Stevens if(iterr!=0) { 107351d315f7SKerry Stevens ithreaderr = 1; 107451d315f7SKerry Stevens } 107551d315f7SKerry Stevens if(PetscThreadGo) { 1076ba61063dSBarry Smith /* reset job, get ready for more */ 107751d315f7SKerry Stevens ierr = pthread_mutex_lock(job_main.mutexarray[ThreadId]); 107851d315f7SKerry Stevens *(job_main.arrThreadReady[ThreadId]) = PETSC_TRUE; 1079ba61063dSBarry Smith /* tell the BOSS that you're ready to work before you go to sleep */ 108051d315f7SKerry Stevens ierr = pthread_cond_signal(job_main.cond1array[ThreadId]); 108151d315f7SKerry Stevens } 108251d315f7SKerry Stevens } 108351d315f7SKerry Stevens return NULL; 108451d315f7SKerry Stevens } 108551d315f7SKerry Stevens 108651d315f7SKerry Stevens #undef __FUNCT__ 108751d315f7SKerry Stevens #define __FUNCT__ "PetscThreadInitialize_Main" 108851d315f7SKerry Stevens void* PetscThreadInitialize_Main(PetscInt N) { 108951d315f7SKerry Stevens PetscInt i,ierr; 109051d315f7SKerry Stevens int status; 109151d315f7SKerry Stevens 109251d315f7SKerry Stevens if(PetscUseThreadPool) { 109351d315f7SKerry Stevens size_t Val1 = (size_t)CACHE_LINE_SIZE; 109451d315f7SKerry Stevens size_t Val2 = (size_t)PetscMaxThreads*CACHE_LINE_SIZE; 109551d315f7SKerry Stevens arrmutex = (char*)memalign(Val1,Val2); 109651d315f7SKerry Stevens arrcond1 = (char*)memalign(Val1,Val2); 109751d315f7SKerry Stevens arrcond2 = (char*)memalign(Val1,Val2); 109851d315f7SKerry Stevens arrstart = (char*)memalign(Val1,Val2); 109951d315f7SKerry Stevens arrready = (char*)memalign(Val1,Val2); 110051d315f7SKerry Stevens job_main.mutexarray = (pthread_mutex_t**)malloc(PetscMaxThreads*sizeof(pthread_mutex_t*)); 110151d315f7SKerry Stevens job_main.cond1array = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*)); 110251d315f7SKerry Stevens job_main.cond2array = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*)); 110351d315f7SKerry Stevens job_main.arrThreadReady = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*)); 1104ba61063dSBarry Smith /* initialize job structure */ 110551d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 110651d315f7SKerry Stevens job_main.mutexarray[i] = (pthread_mutex_t*)(arrmutex+CACHE_LINE_SIZE*i); 110751d315f7SKerry Stevens job_main.cond1array[i] = (pthread_cond_t*)(arrcond1+CACHE_LINE_SIZE*i); 110851d315f7SKerry Stevens job_main.cond2array[i] = (pthread_cond_t*)(arrcond2+CACHE_LINE_SIZE*i); 110951d315f7SKerry Stevens job_main.arrThreadReady[i] = (PetscBool*)(arrready+CACHE_LINE_SIZE*i); 111051d315f7SKerry Stevens } 111151d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 111251d315f7SKerry Stevens ierr = pthread_mutex_init(job_main.mutexarray[i],NULL); 111351d315f7SKerry Stevens ierr = pthread_cond_init(job_main.cond1array[i],NULL); 111451d315f7SKerry Stevens ierr = pthread_cond_init(job_main.cond2array[i],NULL); 111551d315f7SKerry Stevens *(job_main.arrThreadReady[i]) = PETSC_FALSE; 111651d315f7SKerry Stevens } 111751d315f7SKerry Stevens job_main.pfunc = NULL; 111851d315f7SKerry Stevens job_main.pdata = (void**)malloc(N*sizeof(void*)); 111951d315f7SKerry Stevens pVal = (int*)malloc(N*sizeof(int)); 1120ba61063dSBarry Smith /* allocate memory in the heap for the thread structure */ 112151d315f7SKerry Stevens PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t)); 1122ba61063dSBarry Smith /* create threads */ 112351d315f7SKerry Stevens for(i=0; i<N; i++) { 112451d315f7SKerry Stevens pVal[i] = i; 112551d315f7SKerry Stevens status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]); 1126ba61063dSBarry Smith /* error check */ 112751d315f7SKerry Stevens } 112851d315f7SKerry Stevens } 112951d315f7SKerry Stevens else { 113051d315f7SKerry Stevens } 113151d315f7SKerry Stevens return NULL; 113251d315f7SKerry Stevens } 113351d315f7SKerry Stevens 113451d315f7SKerry Stevens #undef __FUNCT__ 113551d315f7SKerry Stevens #define __FUNCT__ "PetscThreadFinalize_Main" 113651d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Main() { 113751d315f7SKerry Stevens int i,ierr; 113851d315f7SKerry Stevens void* jstatus; 113951d315f7SKerry Stevens 114051d315f7SKerry Stevens PetscFunctionBegin; 114151d315f7SKerry Stevens 114251d315f7SKerry Stevens if(PetscUseThreadPool) { 1143ba61063dSBarry Smith MainJob(FuncFinish,NULL,PetscMaxThreads); /* set up job and broadcast work */ 1144ba61063dSBarry Smith /* join the threads */ 114551d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 1146ba61063dSBarry Smith ierr = pthread_join(PetscThreadPoint[i],&jstatus);CHKERRQ(ierr); 114751d315f7SKerry Stevens } 114851d315f7SKerry Stevens free(PetscThreadPoint); 114951d315f7SKerry Stevens free(arrmutex); 115051d315f7SKerry Stevens free(arrcond1); 115151d315f7SKerry Stevens free(arrcond2); 115251d315f7SKerry Stevens free(arrstart); 115351d315f7SKerry Stevens free(arrready); 115451d315f7SKerry Stevens free(job_main.pdata); 115551d315f7SKerry Stevens free(pVal); 115651d315f7SKerry Stevens } 115751d315f7SKerry Stevens PetscFunctionReturn(0); 115851d315f7SKerry Stevens } 115951d315f7SKerry Stevens 116051d315f7SKerry Stevens #undef __FUNCT__ 116151d315f7SKerry Stevens #define __FUNCT__ "MainWait_Main" 116251d315f7SKerry Stevens void MainWait_Main() { 116351d315f7SKerry Stevens int i,ierr; 116451d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 116551d315f7SKerry Stevens ierr = pthread_mutex_lock(job_main.mutexarray[i]); 116651d315f7SKerry Stevens while(*(job_main.arrThreadReady[i])==PETSC_FALSE) { 116751d315f7SKerry Stevens ierr = pthread_cond_wait(job_main.cond1array[i],job_main.mutexarray[i]); 116851d315f7SKerry Stevens } 116951d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_main.mutexarray[i]); 117051d315f7SKerry Stevens } 117151d315f7SKerry Stevens } 117251d315f7SKerry Stevens 117351d315f7SKerry Stevens #undef __FUNCT__ 117451d315f7SKerry Stevens #define __FUNCT__ "MainJob_Main" 117551d315f7SKerry Stevens PetscErrorCode MainJob_Main(void* (*pFunc)(void*),void** data,PetscInt n) { 117651d315f7SKerry Stevens int i,ierr; 117751d315f7SKerry Stevens PetscErrorCode ijoberr = 0; 117851d315f7SKerry Stevens if(PetscUseThreadPool) { 1179ba61063dSBarry Smith MainWait(); /* you know everyone is waiting to be signalled! */ 118051d315f7SKerry Stevens job_main.pfunc = pFunc; 118151d315f7SKerry Stevens job_main.pdata = data; 118251d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 1183ba61063dSBarry Smith *(job_main.arrThreadReady[i]) = PETSC_FALSE; /* why do this? suppose you get into MainWait first */ 118451d315f7SKerry Stevens } 1185ba61063dSBarry Smith /* tell the threads to go to work */ 118651d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 118751d315f7SKerry Stevens ierr = pthread_cond_signal(job_main.cond2array[i]); 118851d315f7SKerry Stevens } 118951d315f7SKerry Stevens if(pFunc!=FuncFinish) { 1190ba61063dSBarry Smith MainWait(); /* why wait after? guarantees that job gets done before proceeding with result collection (if any) */ 119151d315f7SKerry Stevens } 119251d315f7SKerry Stevens } 119351d315f7SKerry Stevens else { 119451d315f7SKerry Stevens pthread_t* apThread = (pthread_t*)malloc(n*sizeof(pthread_t)); 119551d315f7SKerry Stevens PetscThreadRun(MPI_COMM_WORLD,pFunc,n,apThread,data); 1196ba61063dSBarry Smith PetscThreadStop(MPI_COMM_WORLD,n,apThread); /* ensures that all threads are finished with the job */ 119751d315f7SKerry Stevens free(apThread); 119851d315f7SKerry Stevens } 119951d315f7SKerry Stevens if(ithreaderr) { 120051d315f7SKerry Stevens ijoberr = ithreaderr; 120151d315f7SKerry Stevens } 120251d315f7SKerry Stevens return ijoberr; 120351d315f7SKerry Stevens } 120451d315f7SKerry Stevens /**** ****/ 120551d315f7SKerry Stevens 120651d315f7SKerry Stevens /**** Chain Thread Functions ****/ 120751d315f7SKerry Stevens void* PetscThreadFunc_Chain(void* arg) { 120851d315f7SKerry Stevens PetscErrorCode iterr; 120951d315f7SKerry Stevens int icorr,ierr; 121051d315f7SKerry Stevens int* pId = (int*)arg; 121151d315f7SKerry Stevens int ThreadId = *pId; 121251d315f7SKerry Stevens int SubWorker = ThreadId + 1; 121351d315f7SKerry Stevens PetscBool PeeOn; 121451d315f7SKerry Stevens cpu_set_t mset; 121551d315f7SKerry Stevens 121651d315f7SKerry Stevens icorr = ThreadCoreAffinity[ThreadId]; 121751d315f7SKerry Stevens CPU_ZERO(&mset); 121851d315f7SKerry Stevens CPU_SET(icorr,&mset); 121951d315f7SKerry Stevens sched_setaffinity(0,sizeof(cpu_set_t),&mset); 122051d315f7SKerry Stevens 122151d315f7SKerry Stevens if(ThreadId==(PetscMaxThreads-1)) { 122251d315f7SKerry Stevens PeeOn = PETSC_TRUE; 122351d315f7SKerry Stevens } 122451d315f7SKerry Stevens else { 122551d315f7SKerry Stevens PeeOn = PETSC_FALSE; 122651d315f7SKerry Stevens } 122751d315f7SKerry Stevens if(PeeOn==PETSC_FALSE) { 1228ba61063dSBarry Smith /* check your subordinate, wait for him to be ready */ 122951d315f7SKerry Stevens ierr = pthread_mutex_lock(job_chain.mutexarray[SubWorker]); 123051d315f7SKerry Stevens while(*(job_chain.arrThreadReady[SubWorker])==PETSC_FALSE) { 1231ba61063dSBarry Smith /* upon entry, automically releases the lock and blocks 1232ba61063dSBarry Smith upon return, has the lock */ 123351d315f7SKerry Stevens ierr = pthread_cond_wait(job_chain.cond1array[SubWorker],job_chain.mutexarray[SubWorker]); 123451d315f7SKerry Stevens } 123551d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_chain.mutexarray[SubWorker]); 1236ba61063dSBarry Smith /* your subordinate is now ready*/ 123751d315f7SKerry Stevens } 123851d315f7SKerry Stevens ierr = pthread_mutex_lock(job_chain.mutexarray[ThreadId]); 1239ba61063dSBarry Smith /* update your ready status */ 124051d315f7SKerry Stevens *(job_chain.arrThreadReady[ThreadId]) = PETSC_TRUE; 124151d315f7SKerry Stevens if(ThreadId==0) { 124251d315f7SKerry Stevens job_chain.eJobStat = JobCompleted; 1243ba61063dSBarry Smith /* signal main */ 124451d315f7SKerry Stevens ierr = pthread_cond_signal(&main_cond); 124551d315f7SKerry Stevens } 124651d315f7SKerry Stevens else { 1247ba61063dSBarry Smith /* tell your boss that you're ready to work */ 124851d315f7SKerry Stevens ierr = pthread_cond_signal(job_chain.cond1array[ThreadId]); 124951d315f7SKerry Stevens } 1250ba61063dSBarry Smith /* the while loop needs to have an exit 1251ba61063dSBarry Smith the 'main' thread can terminate all the threads by performing a broadcast 1252ba61063dSBarry Smith and calling FuncFinish */ 125351d315f7SKerry Stevens while(PetscThreadGo) { 1254ba61063dSBarry Smith /* need to check the condition to ensure we don't have to wait 1255ba61063dSBarry Smith waiting when you don't have to causes problems 1256ba61063dSBarry Smith also need to check the condition to ensure proper handling of spurious wakeups */ 125751d315f7SKerry Stevens while(*(job_chain.arrThreadReady[ThreadId])==PETSC_TRUE) { 1258ba61063dSBarry Smith /*upon entry, automically releases the lock and blocks 1259ba61063dSBarry Smith upon return, has the lock */ 126051d315f7SKerry Stevens ierr = pthread_cond_wait(job_chain.cond2array[ThreadId],job_chain.mutexarray[ThreadId]); 126151d315f7SKerry Stevens *(job_chain.arrThreadStarted[ThreadId]) = PETSC_TRUE; 126251d315f7SKerry Stevens *(job_chain.arrThreadReady[ThreadId]) = PETSC_FALSE; 126351d315f7SKerry Stevens } 126451d315f7SKerry Stevens if(ThreadId==0) { 126551d315f7SKerry Stevens job_chain.startJob = PETSC_FALSE; 126651d315f7SKerry Stevens job_chain.eJobStat = ThreadsWorking; 126751d315f7SKerry Stevens } 126851d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_chain.mutexarray[ThreadId]); 126951d315f7SKerry Stevens if(PeeOn==PETSC_FALSE) { 1270ba61063dSBarry Smith /* tell your subworker it's time to get to work */ 127151d315f7SKerry Stevens ierr = pthread_cond_signal(job_chain.cond2array[SubWorker]); 127251d315f7SKerry Stevens } 1273ba61063dSBarry Smith /* do your job */ 127451d315f7SKerry Stevens if(job_chain.pdata==NULL) { 127551d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_chain.pfunc(job_chain.pdata); 127651d315f7SKerry Stevens } 127751d315f7SKerry Stevens else { 127851d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_chain.pfunc(job_chain.pdata[ThreadId]); 127951d315f7SKerry Stevens } 128051d315f7SKerry Stevens if(iterr!=0) { 128151d315f7SKerry Stevens ithreaderr = 1; 128251d315f7SKerry Stevens } 128351d315f7SKerry Stevens if(PetscThreadGo) { 1284ba61063dSBarry Smith /* reset job, get ready for more */ 128551d315f7SKerry Stevens if(PeeOn==PETSC_FALSE) { 1286ba61063dSBarry Smith /* check your subordinate, wait for him to be ready 1287ba61063dSBarry Smith how do you know for a fact that your subordinate has actually started? */ 128851d315f7SKerry Stevens ierr = pthread_mutex_lock(job_chain.mutexarray[SubWorker]); 128951d315f7SKerry Stevens while(*(job_chain.arrThreadReady[SubWorker])==PETSC_FALSE||*(job_chain.arrThreadStarted[SubWorker])==PETSC_FALSE) { 1290ba61063dSBarry Smith /* upon entry, automically releases the lock and blocks 1291ba61063dSBarry Smith upon return, has the lock */ 129251d315f7SKerry Stevens ierr = pthread_cond_wait(job_chain.cond1array[SubWorker],job_chain.mutexarray[SubWorker]); 129351d315f7SKerry Stevens } 129451d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_chain.mutexarray[SubWorker]); 1295ba61063dSBarry Smith /* your subordinate is now ready */ 129651d315f7SKerry Stevens } 129751d315f7SKerry Stevens ierr = pthread_mutex_lock(job_chain.mutexarray[ThreadId]); 129851d315f7SKerry Stevens *(job_chain.arrThreadReady[ThreadId]) = PETSC_TRUE; 129951d315f7SKerry Stevens if(ThreadId==0) { 1300ba61063dSBarry Smith job_chain.eJobStat = JobCompleted; /* foreman: last thread to complete, guaranteed! */ 1301ba61063dSBarry Smith /* root thread (foreman) signals 'main' */ 130251d315f7SKerry Stevens ierr = pthread_cond_signal(&main_cond); 130351d315f7SKerry Stevens } 130451d315f7SKerry Stevens else { 1305ba61063dSBarry Smith /* signal your boss before you go to sleep */ 130651d315f7SKerry Stevens ierr = pthread_cond_signal(job_chain.cond1array[ThreadId]); 130751d315f7SKerry Stevens } 130851d315f7SKerry Stevens } 130951d315f7SKerry Stevens } 131051d315f7SKerry Stevens return NULL; 131151d315f7SKerry Stevens } 131251d315f7SKerry Stevens 131351d315f7SKerry Stevens #undef __FUNCT__ 131451d315f7SKerry Stevens #define __FUNCT__ "PetscThreadInitialize_Chain" 131551d315f7SKerry Stevens void* PetscThreadInitialize_Chain(PetscInt N) { 131651d315f7SKerry Stevens PetscInt i,ierr; 131751d315f7SKerry Stevens int status; 131851d315f7SKerry Stevens 131951d315f7SKerry Stevens if(PetscUseThreadPool) { 132051d315f7SKerry Stevens size_t Val1 = (size_t)CACHE_LINE_SIZE; 132151d315f7SKerry Stevens size_t Val2 = (size_t)PetscMaxThreads*CACHE_LINE_SIZE; 132251d315f7SKerry Stevens arrmutex = (char*)memalign(Val1,Val2); 132351d315f7SKerry Stevens arrcond1 = (char*)memalign(Val1,Val2); 132451d315f7SKerry Stevens arrcond2 = (char*)memalign(Val1,Val2); 132551d315f7SKerry Stevens arrstart = (char*)memalign(Val1,Val2); 132651d315f7SKerry Stevens arrready = (char*)memalign(Val1,Val2); 132751d315f7SKerry Stevens job_chain.mutexarray = (pthread_mutex_t**)malloc(PetscMaxThreads*sizeof(pthread_mutex_t*)); 132851d315f7SKerry Stevens job_chain.cond1array = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*)); 132951d315f7SKerry Stevens job_chain.cond2array = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*)); 133051d315f7SKerry Stevens job_chain.arrThreadStarted = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*)); 133151d315f7SKerry Stevens job_chain.arrThreadReady = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*)); 1332ba61063dSBarry Smith /* initialize job structure */ 133351d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 133451d315f7SKerry Stevens job_chain.mutexarray[i] = (pthread_mutex_t*)(arrmutex+CACHE_LINE_SIZE*i); 133551d315f7SKerry Stevens job_chain.cond1array[i] = (pthread_cond_t*)(arrcond1+CACHE_LINE_SIZE*i); 133651d315f7SKerry Stevens job_chain.cond2array[i] = (pthread_cond_t*)(arrcond2+CACHE_LINE_SIZE*i); 133751d315f7SKerry Stevens job_chain.arrThreadStarted[i] = (PetscBool*)(arrstart+CACHE_LINE_SIZE*i); 133851d315f7SKerry Stevens job_chain.arrThreadReady[i] = (PetscBool*)(arrready+CACHE_LINE_SIZE*i); 133951d315f7SKerry Stevens } 134051d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 134151d315f7SKerry Stevens ierr = pthread_mutex_init(job_chain.mutexarray[i],NULL); 134251d315f7SKerry Stevens ierr = pthread_cond_init(job_chain.cond1array[i],NULL); 134351d315f7SKerry Stevens ierr = pthread_cond_init(job_chain.cond2array[i],NULL); 134451d315f7SKerry Stevens *(job_chain.arrThreadStarted[i]) = PETSC_FALSE; 134551d315f7SKerry Stevens *(job_chain.arrThreadReady[i]) = PETSC_FALSE; 134651d315f7SKerry Stevens } 134751d315f7SKerry Stevens job_chain.pfunc = NULL; 134851d315f7SKerry Stevens job_chain.pdata = (void**)malloc(N*sizeof(void*)); 134951d315f7SKerry Stevens job_chain.startJob = PETSC_FALSE; 135051d315f7SKerry Stevens job_chain.eJobStat = JobInitiated; 135151d315f7SKerry Stevens pVal = (int*)malloc(N*sizeof(int)); 1352ba61063dSBarry Smith /* allocate memory in the heap for the thread structure */ 135351d315f7SKerry Stevens PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t)); 1354ba61063dSBarry Smith /* create threads */ 135551d315f7SKerry Stevens for(i=0; i<N; i++) { 135651d315f7SKerry Stevens pVal[i] = i; 135751d315f7SKerry Stevens status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]); 1358ba61063dSBarry Smith /* should check error */ 135951d315f7SKerry Stevens } 136051d315f7SKerry Stevens } 136151d315f7SKerry Stevens else { 136251d315f7SKerry Stevens } 136351d315f7SKerry Stevens return NULL; 136451d315f7SKerry Stevens } 136551d315f7SKerry Stevens 136651d315f7SKerry Stevens 136751d315f7SKerry Stevens #undef __FUNCT__ 136851d315f7SKerry Stevens #define __FUNCT__ "PetscThreadFinalize_Chain" 136951d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Chain() { 137051d315f7SKerry Stevens int i,ierr; 137151d315f7SKerry Stevens void* jstatus; 137251d315f7SKerry Stevens 137351d315f7SKerry Stevens PetscFunctionBegin; 137451d315f7SKerry Stevens 137551d315f7SKerry Stevens if(PetscUseThreadPool) { 1376ba61063dSBarry Smith MainJob(FuncFinish,NULL,PetscMaxThreads); /* set up job and broadcast work */ 1377ba61063dSBarry Smith /* join the threads */ 137851d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 137951d315f7SKerry Stevens ierr = pthread_join(PetscThreadPoint[i],&jstatus); 1380ba61063dSBarry Smith /* should check error */ 138151d315f7SKerry Stevens } 138251d315f7SKerry Stevens free(PetscThreadPoint); 138351d315f7SKerry Stevens free(arrmutex); 138451d315f7SKerry Stevens free(arrcond1); 138551d315f7SKerry Stevens free(arrcond2); 138651d315f7SKerry Stevens free(arrstart); 138751d315f7SKerry Stevens free(arrready); 138851d315f7SKerry Stevens free(job_chain.pdata); 138951d315f7SKerry Stevens free(pVal); 139051d315f7SKerry Stevens } 139151d315f7SKerry Stevens else { 139251d315f7SKerry Stevens } 139351d315f7SKerry Stevens PetscFunctionReturn(0); 139451d315f7SKerry Stevens } 139551d315f7SKerry Stevens 139651d315f7SKerry Stevens #undef __FUNCT__ 139751d315f7SKerry Stevens #define __FUNCT__ "MainWait_Chain" 139851d315f7SKerry Stevens void MainWait_Chain() { 139951d315f7SKerry Stevens int ierr; 140051d315f7SKerry Stevens ierr = pthread_mutex_lock(job_chain.mutexarray[0]); 140151d315f7SKerry Stevens while(job_chain.eJobStat<JobCompleted||job_chain.startJob==PETSC_TRUE) { 140251d315f7SKerry Stevens ierr = pthread_cond_wait(&main_cond,job_chain.mutexarray[0]); 140351d315f7SKerry Stevens } 140451d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_chain.mutexarray[0]); 140551d315f7SKerry Stevens } 140651d315f7SKerry Stevens 140751d315f7SKerry Stevens #undef __FUNCT__ 140851d315f7SKerry Stevens #define __FUNCT__ "MainJob_Chain" 140951d315f7SKerry Stevens PetscErrorCode MainJob_Chain(void* (*pFunc)(void*),void** data,PetscInt n) { 141051d315f7SKerry Stevens int i,ierr; 141151d315f7SKerry Stevens PetscErrorCode ijoberr = 0; 141251d315f7SKerry Stevens if(PetscUseThreadPool) { 141351d315f7SKerry Stevens MainWait(); 141451d315f7SKerry Stevens job_chain.pfunc = pFunc; 141551d315f7SKerry Stevens job_chain.pdata = data; 141651d315f7SKerry Stevens job_chain.startJob = PETSC_TRUE; 141751d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 141851d315f7SKerry Stevens *(job_chain.arrThreadStarted[i]) = PETSC_FALSE; 141951d315f7SKerry Stevens } 142051d315f7SKerry Stevens job_chain.eJobStat = JobInitiated; 142151d315f7SKerry Stevens ierr = pthread_cond_signal(job_chain.cond2array[0]); 142251d315f7SKerry Stevens if(pFunc!=FuncFinish) { 1423ba61063dSBarry Smith MainWait(); /* why wait after? guarantees that job gets done before proceeding with result collection (if any) */ 142451d315f7SKerry Stevens } 142551d315f7SKerry Stevens } 142651d315f7SKerry Stevens else { 142751d315f7SKerry Stevens pthread_t* apThread = (pthread_t*)malloc(n*sizeof(pthread_t)); 142851d315f7SKerry Stevens PetscThreadRun(MPI_COMM_WORLD,pFunc,n,apThread,data); 1429ba61063dSBarry Smith PetscThreadStop(MPI_COMM_WORLD,n,apThread); /* ensures that all threads are finished with the job */ 143051d315f7SKerry Stevens free(apThread); 143151d315f7SKerry Stevens } 143251d315f7SKerry Stevens if(ithreaderr) { 143351d315f7SKerry Stevens ijoberr = ithreaderr; 143451d315f7SKerry Stevens } 143551d315f7SKerry Stevens return ijoberr; 143651d315f7SKerry Stevens } 143751d315f7SKerry Stevens /**** ****/ 143851d315f7SKerry Stevens 1439ba61063dSBarry Smith #if defined(PETSC_HAVE_PTHREAD_BARRIER) 144051d315f7SKerry Stevens /**** True Thread Functions ****/ 144151d315f7SKerry Stevens void* PetscThreadFunc_True(void* arg) { 144251d315f7SKerry Stevens int icorr,ierr,iVal; 144351dcc849SKerry Stevens int* pId = (int*)arg; 144451dcc849SKerry Stevens int ThreadId = *pId; 14450ca81413SKerry Stevens PetscErrorCode iterr; 144651d315f7SKerry Stevens cpu_set_t mset; 144751dcc849SKerry Stevens 144851d315f7SKerry Stevens icorr = ThreadCoreAffinity[ThreadId]; 144951d315f7SKerry Stevens CPU_ZERO(&mset); 145051d315f7SKerry Stevens CPU_SET(icorr,&mset); 145151d315f7SKerry Stevens sched_setaffinity(0,sizeof(cpu_set_t),&mset); 145251d315f7SKerry Stevens 145351d315f7SKerry Stevens ierr = pthread_mutex_lock(&job_true.mutex); 145451d315f7SKerry Stevens job_true.iNumReadyThreads++; 145551d315f7SKerry Stevens if(job_true.iNumReadyThreads==PetscMaxThreads) { 145651dcc849SKerry Stevens ierr = pthread_cond_signal(&main_cond); 145751dcc849SKerry Stevens } 1458ba61063dSBarry Smith /*the while loop needs to have an exit 1459ba61063dSBarry Smith the 'main' thread can terminate all the threads by performing a broadcast 1460ba61063dSBarry Smith and calling FuncFinish */ 146151dcc849SKerry Stevens while(PetscThreadGo) { 1462ba61063dSBarry Smith /*need to check the condition to ensure we don't have to wait 1463ba61063dSBarry Smith waiting when you don't have to causes problems 1464ba61063dSBarry Smith also need to wait if another thread sneaks in and messes with the predicate */ 146551d315f7SKerry Stevens while(job_true.startJob==PETSC_FALSE&&job_true.iNumJobThreads==0) { 1466ba61063dSBarry Smith /* upon entry, automically releases the lock and blocks 1467ba61063dSBarry Smith upon return, has the lock */ 146851d315f7SKerry Stevens ierr = pthread_cond_wait(&job_true.cond,&job_true.mutex); 146951dcc849SKerry Stevens } 147051d315f7SKerry Stevens job_true.startJob = PETSC_FALSE; 147151d315f7SKerry Stevens job_true.iNumJobThreads--; 147251d315f7SKerry Stevens job_true.iNumReadyThreads--; 147351d315f7SKerry Stevens iVal = PetscMaxThreads-job_true.iNumReadyThreads-1; 147451d315f7SKerry Stevens pthread_mutex_unlock(&job_true.mutex); 147551d315f7SKerry Stevens if(job_true.pdata==NULL) { 147651d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_true.pfunc(job_true.pdata); 147751dcc849SKerry Stevens } 147851dcc849SKerry Stevens else { 147951d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_true.pfunc(job_true.pdata[iVal]); 148051dcc849SKerry Stevens } 14810ca81413SKerry Stevens if(iterr!=0) { 14820ca81413SKerry Stevens ithreaderr = 1; 14830ca81413SKerry Stevens } 1484ba61063dSBarry Smith /* the barrier is necessary BECAUSE: look at job_true.iNumReadyThreads 1485ba61063dSBarry Smith what happens if a thread finishes before they all start? BAD! 1486ba61063dSBarry Smith what happens if a thread finishes before any else start? BAD! */ 1487ba61063dSBarry Smith pthread_barrier_wait(job_true.pbarr); /* ensures all threads are finished */ 1488ba61063dSBarry Smith /* reset job */ 148951dcc849SKerry Stevens if(PetscThreadGo) { 149051d315f7SKerry Stevens pthread_mutex_lock(&job_true.mutex); 149151d315f7SKerry Stevens job_true.iNumReadyThreads++; 149251d315f7SKerry Stevens if(job_true.iNumReadyThreads==PetscMaxThreads) { 1493ba61063dSBarry Smith /* signal the 'main' thread that the job is done! (only done once) */ 149451dcc849SKerry Stevens ierr = pthread_cond_signal(&main_cond); 149551dcc849SKerry Stevens } 149651dcc849SKerry Stevens } 149751dcc849SKerry Stevens } 149851dcc849SKerry Stevens return NULL; 149951dcc849SKerry Stevens } 150051dcc849SKerry Stevens 1501f09cb4aaSKerry Stevens #undef __FUNCT__ 150251d315f7SKerry Stevens #define __FUNCT__ "PetscThreadInitialize_True" 150351d315f7SKerry Stevens void* PetscThreadInitialize_True(PetscInt N) { 150451dcc849SKerry Stevens PetscInt i; 150551dcc849SKerry Stevens int status; 15060ca81413SKerry Stevens 15070ca81413SKerry Stevens if(PetscUseThreadPool) { 1508f09cb4aaSKerry Stevens pVal = (int*)malloc(N*sizeof(int)); 1509ba61063dSBarry Smith /* allocate memory in the heap for the thread structure */ 151051dcc849SKerry Stevens PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t)); 1511ba61063dSBarry Smith BarrPoint = (pthread_barrier_t*)malloc((N+1)*sizeof(pthread_barrier_t)); /* BarrPoint[0] makes no sense, don't use it! */ 151251d315f7SKerry Stevens job_true.pdata = (void**)malloc(N*sizeof(void*)); 151351dcc849SKerry Stevens for(i=0; i<N; i++) { 1514f09cb4aaSKerry Stevens pVal[i] = i; 1515f09cb4aaSKerry Stevens status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]); 1516ba61063dSBarry Smith /* error check to ensure proper thread creation */ 151751dcc849SKerry Stevens status = pthread_barrier_init(&BarrPoint[i+1],NULL,i+1); 1518ba61063dSBarry Smith /* should check error */ 151951dcc849SKerry Stevens } 15200ca81413SKerry Stevens } 15210ca81413SKerry Stevens else { 15220ca81413SKerry Stevens } 152351dcc849SKerry Stevens return NULL; 152451dcc849SKerry Stevens } 152551dcc849SKerry Stevens 1526f09cb4aaSKerry Stevens 1527f09cb4aaSKerry Stevens #undef __FUNCT__ 152851d315f7SKerry Stevens #define __FUNCT__ "PetscThreadFinalize_True" 152951d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_True() { 153051dcc849SKerry Stevens int i,ierr; 153151dcc849SKerry Stevens void* jstatus; 153251dcc849SKerry Stevens 153351dcc849SKerry Stevens PetscFunctionBegin; 15340ca81413SKerry Stevens 15350ca81413SKerry Stevens if(PetscUseThreadPool) { 1536ba61063dSBarry Smith MainJob(FuncFinish,NULL,PetscMaxThreads); /* set up job and broadcast work */ 1537ba61063dSBarry Smith /* join the threads */ 153851dcc849SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 153951dcc849SKerry Stevens ierr = pthread_join(PetscThreadPoint[i],&jstatus); 1540ba61063dSBarry Smith /* should check error */ 154151dcc849SKerry Stevens } 154251dcc849SKerry Stevens free(BarrPoint); 154351dcc849SKerry Stevens free(PetscThreadPoint); 15440ca81413SKerry Stevens } 15450ca81413SKerry Stevens else { 15460ca81413SKerry Stevens } 154751dcc849SKerry Stevens PetscFunctionReturn(0); 154851dcc849SKerry Stevens } 154951dcc849SKerry Stevens 1550f09cb4aaSKerry Stevens #undef __FUNCT__ 155151d315f7SKerry Stevens #define __FUNCT__ "MainWait_True" 155251d315f7SKerry Stevens void MainWait_True() { 155351dcc849SKerry Stevens int ierr; 155451d315f7SKerry Stevens while(job_true.iNumReadyThreads<PetscMaxThreads||job_true.startJob==PETSC_TRUE) { 155551d315f7SKerry Stevens ierr = pthread_cond_wait(&main_cond,&job_true.mutex); 155651dcc849SKerry Stevens } 155751d315f7SKerry Stevens ierr = pthread_mutex_unlock(&job_true.mutex); 155851dcc849SKerry Stevens } 155951dcc849SKerry Stevens 1560f09cb4aaSKerry Stevens #undef __FUNCT__ 156151d315f7SKerry Stevens #define __FUNCT__ "MainJob_True" 156251d315f7SKerry Stevens PetscErrorCode MainJob_True(void* (*pFunc)(void*),void** data,PetscInt n) { 156351dcc849SKerry Stevens int ierr; 15640ca81413SKerry Stevens PetscErrorCode ijoberr = 0; 15650ca81413SKerry Stevens if(PetscUseThreadPool) { 15660ca81413SKerry Stevens MainWait(); 156751d315f7SKerry Stevens job_true.pfunc = pFunc; 156851d315f7SKerry Stevens job_true.pdata = data; 156951d315f7SKerry Stevens job_true.pbarr = &BarrPoint[n]; 157051d315f7SKerry Stevens job_true.iNumJobThreads = n; 157151d315f7SKerry Stevens job_true.startJob = PETSC_TRUE; 157251d315f7SKerry Stevens ierr = pthread_cond_broadcast(&job_true.cond); 15730ca81413SKerry Stevens if(pFunc!=FuncFinish) { 1574ba61063dSBarry Smith MainWait(); /* why wait after? guarantees that job gets done */ 15750ca81413SKerry Stevens } 15760ca81413SKerry Stevens } 15770ca81413SKerry Stevens else { 15780ca81413SKerry Stevens pthread_t* apThread = (pthread_t*)malloc(n*sizeof(pthread_t)); 15790ca81413SKerry Stevens PetscThreadRun(MPI_COMM_WORLD,pFunc,n,apThread,data); 1580ba61063dSBarry Smith PetscThreadStop(MPI_COMM_WORLD,n,apThread); /* ensures that all threads are finished with the job */ 15810ca81413SKerry Stevens free(apThread); 15820ca81413SKerry Stevens } 15830ca81413SKerry Stevens if(ithreaderr) { 15840ca81413SKerry Stevens ijoberr = ithreaderr; 15850ca81413SKerry Stevens } 15860ca81413SKerry Stevens return ijoberr; 158751dcc849SKerry Stevens } 158851d315f7SKerry Stevens /**** ****/ 1589ba61063dSBarry Smith #endif 159051dcc849SKerry Stevens 159151dcc849SKerry Stevens void* FuncFinish(void* arg) { 159251dcc849SKerry Stevens PetscThreadGo = PETSC_FALSE; 15930ca81413SKerry Stevens return(0); 159451dcc849SKerry Stevens } 1595ba61063dSBarry Smith 1596ba61063dSBarry Smith #endif 1597