1*9e800a48SKerry Stevens //new kds file - implements all thread pool versions 2e5c89e4eSSatish Balay /* 3e5c89e4eSSatish Balay 4e5c89e4eSSatish Balay This file defines part of the initialization of PETSc 5e5c89e4eSSatish Balay 6e5c89e4eSSatish Balay This file uses regular malloc and free because it cannot know 7e5c89e4eSSatish Balay what malloc is being used until it has already processed the input. 8e5c89e4eSSatish Balay */ 9e5c89e4eSSatish Balay 1051d315f7SKerry Stevens #define _GNU_SOURCE 1151d315f7SKerry Stevens #include <sched.h> 12c6db04a5SJed Brown #include <petscsys.h> /*I "petscsys.h" I*/ 1351dcc849SKerry Stevens #include <pthread.h> 1451d315f7SKerry Stevens #include <sys/sysinfo.h> 1551d315f7SKerry Stevens #include <unistd.h> 16e5c89e4eSSatish Balay #if defined(PETSC_HAVE_STDLIB_H) 17e5c89e4eSSatish Balay #include <stdlib.h> 18e5c89e4eSSatish Balay #endif 19e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H) 20e5c89e4eSSatish Balay #include <malloc.h> 21e5c89e4eSSatish Balay #endif 22555d055bSBarry Smith #if defined(PETSC_HAVE_VALGRIND) 23555d055bSBarry Smith #include <valgrind/valgrind.h> 24555d055bSBarry Smith #endif 25555d055bSBarry Smith 26e5c89e4eSSatish Balay /* ------------------------Nasty global variables -------------------------------*/ 27e5c89e4eSSatish Balay /* 28e5c89e4eSSatish Balay Indicates if PETSc started up MPI, or it was 29e5c89e4eSSatish Balay already started before PETSc was initialized. 30e5c89e4eSSatish Balay */ 317087cfbeSBarry Smith PetscBool PetscBeganMPI = PETSC_FALSE; 327087cfbeSBarry Smith PetscBool PetscInitializeCalled = PETSC_FALSE; 337087cfbeSBarry Smith PetscBool PetscFinalizeCalled = PETSC_FALSE; 3451dcc849SKerry Stevens PetscBool PetscUseThreadPool = PETSC_FALSE; 3551dcc849SKerry Stevens PetscBool PetscThreadGo = PETSC_TRUE; 367087cfbeSBarry Smith PetscMPIInt PetscGlobalRank = -1; 377087cfbeSBarry Smith PetscMPIInt PetscGlobalSize = -1; 3851dcc849SKerry Stevens PetscMPIInt PetscMaxThreads = 2; 3951dcc849SKerry Stevens pthread_t* PetscThreadPoint; 4051d315f7SKerry Stevens pthread_barrier_t* BarrPoint; //used by 'true' thread pool 4151d315f7SKerry Stevens PetscErrorCode ithreaderr = 0; 42f09cb4aaSKerry Stevens int* pVal; 4351dcc849SKerry Stevens 4451d315f7SKerry Stevens #define CACHE_LINE_SIZE 64 //used by 'chain', 'main','tree' thread pools 4551d315f7SKerry Stevens int* ThreadCoreAffinity; 4651d315f7SKerry Stevens 4751d315f7SKerry Stevens typedef enum {JobInitiated,ThreadsWorking,JobCompleted} estat; //used by 'chain','tree' thread pool 4851d315f7SKerry Stevens 4951d315f7SKerry Stevens typedef struct { 5051d315f7SKerry Stevens pthread_mutex_t** mutexarray; 5151d315f7SKerry Stevens pthread_cond_t** cond1array; 5251d315f7SKerry Stevens pthread_cond_t** cond2array; 5351d315f7SKerry Stevens void* (*pfunc)(void*); 5451d315f7SKerry Stevens void** pdata; 5551d315f7SKerry Stevens PetscBool startJob; 5651d315f7SKerry Stevens estat eJobStat; 5751d315f7SKerry Stevens PetscBool** arrThreadStarted; 5851d315f7SKerry Stevens PetscBool** arrThreadReady; 5951d315f7SKerry Stevens } sjob_tree; 6051d315f7SKerry Stevens sjob_tree job_tree; 6151d315f7SKerry Stevens typedef struct { 6251d315f7SKerry Stevens pthread_mutex_t** mutexarray; 6351d315f7SKerry Stevens pthread_cond_t** cond1array; 6451d315f7SKerry Stevens pthread_cond_t** cond2array; 6551d315f7SKerry Stevens void* (*pfunc)(void*); 6651d315f7SKerry Stevens void** pdata; 6751d315f7SKerry Stevens PetscBool** arrThreadReady; 6851d315f7SKerry Stevens } sjob_main; 6951d315f7SKerry Stevens sjob_main job_main; 7051d315f7SKerry Stevens typedef struct { 7151d315f7SKerry Stevens pthread_mutex_t** mutexarray; 7251d315f7SKerry Stevens pthread_cond_t** cond1array; 7351d315f7SKerry Stevens pthread_cond_t** cond2array; 7451d315f7SKerry Stevens void* (*pfunc)(void*); 7551d315f7SKerry Stevens void** pdata; 7651d315f7SKerry Stevens PetscBool startJob; 7751d315f7SKerry Stevens estat eJobStat; 7851d315f7SKerry Stevens PetscBool** arrThreadStarted; 7951d315f7SKerry Stevens PetscBool** arrThreadReady; 8051d315f7SKerry Stevens } sjob_chain; 8151d315f7SKerry Stevens sjob_chain job_chain; 8251dcc849SKerry Stevens typedef struct { 8351dcc849SKerry Stevens pthread_mutex_t mutex; 8451dcc849SKerry Stevens pthread_cond_t cond; 8551dcc849SKerry Stevens void* (*pfunc)(void*); 8651dcc849SKerry Stevens void** pdata; 8751dcc849SKerry Stevens pthread_barrier_t* pbarr; 8851dcc849SKerry Stevens int iNumJobThreads; 8951dcc849SKerry Stevens int iNumReadyThreads; 9051dcc849SKerry Stevens PetscBool startJob; 9151d315f7SKerry Stevens } sjob_true; 9251d315f7SKerry Stevens sjob_true job_true = {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER,NULL,NULL,NULL,0,0,PETSC_FALSE}; 9351dcc849SKerry Stevens 9451d315f7SKerry Stevens pthread_cond_t main_cond = PTHREAD_COND_INITIALIZER; //used by 'true', 'chain','tree' thread pools 9551d315f7SKerry Stevens char* arrmutex; //used by 'chain','main','tree' thread pools 9651d315f7SKerry Stevens char* arrcond1; //used by 'chain','main','tree' thread pools 9751d315f7SKerry Stevens char* arrcond2; //used by 'chain','main','tree' thread pools 9851d315f7SKerry Stevens char* arrstart; //used by 'chain','main','tree' thread pools 9951d315f7SKerry Stevens char* arrready; //used by 'chain','main','tree' thread pools 10051dcc849SKerry Stevens 10151d315f7SKerry Stevens /* Function Pointers */ 10251d315f7SKerry Stevens void* (*PetscThreadFunc)(void*) = NULL; 10351d315f7SKerry Stevens void* (*PetscThreadInitialize)(PetscInt) = NULL; 10451d315f7SKerry Stevens PetscErrorCode (*PetscThreadFinalize)(void) = NULL; 10551d315f7SKerry Stevens void (*MainWait)(void) = NULL; 10651d315f7SKerry Stevens PetscErrorCode (*MainJob)(void* (*pFunc)(void*),void**,PetscInt) = NULL; 10751d315f7SKerry Stevens /**** Tree Functions ****/ 10851d315f7SKerry Stevens void* PetscThreadFunc_Tree(void*); 10951d315f7SKerry Stevens void* PetscThreadInitialize_Tree(PetscInt); 11051d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Tree(void); 11151d315f7SKerry Stevens void MainWait_Tree(void); 11251d315f7SKerry Stevens PetscErrorCode MainJob_Tree(void* (*pFunc)(void*),void**,PetscInt); 11351d315f7SKerry Stevens /**** Main Functions ****/ 11451d315f7SKerry Stevens void* PetscThreadFunc_Main(void*); 11551d315f7SKerry Stevens void* PetscThreadInitialize_Main(PetscInt); 11651d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Main(void); 11751d315f7SKerry Stevens void MainWait_Main(void); 11851d315f7SKerry Stevens PetscErrorCode MainJob_Main(void* (*pFunc)(void*),void**,PetscInt); 11951d315f7SKerry Stevens /**** Chain Functions ****/ 12051d315f7SKerry Stevens void* PetscThreadFunc_Chain(void*); 12151d315f7SKerry Stevens void* PetscThreadInitialize_Chain(PetscInt); 12251d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Chain(void); 12351d315f7SKerry Stevens void MainWait_Chain(void); 12451d315f7SKerry Stevens PetscErrorCode MainJob_Chain(void* (*pFunc)(void*),void**,PetscInt); 12551d315f7SKerry Stevens /**** True Functions ****/ 12651d315f7SKerry Stevens void* PetscThreadFunc_True(void*); 12751d315f7SKerry Stevens void* PetscThreadInitialize_True(PetscInt); 12851d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_True(void); 12951d315f7SKerry Stevens void MainWait_True(void); 13051d315f7SKerry Stevens PetscErrorCode MainJob_True(void* (*pFunc)(void*),void**,PetscInt); 13151d315f7SKerry Stevens /**** ****/ 13251d315f7SKerry Stevens 13351dcc849SKerry Stevens void* FuncFinish(void*); 1340ca81413SKerry Stevens void* PetscThreadRun(MPI_Comm Comm,void* (*pFunc)(void*),int,pthread_t*,void**); 1350ca81413SKerry Stevens void* PetscThreadStop(MPI_Comm Comm,int,pthread_t*); 136e5c89e4eSSatish Balay 137e5c89e4eSSatish Balay #if defined(PETSC_USE_COMPLEX) 138e5c89e4eSSatish Balay #if defined(PETSC_COMPLEX_INSTANTIATE) 139e5c89e4eSSatish Balay template <> class std::complex<double>; /* instantiate complex template class */ 140e5c89e4eSSatish Balay #endif 1412c876bd9SBarry Smith #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX) 1427087cfbeSBarry Smith MPI_Datatype MPI_C_DOUBLE_COMPLEX; 1437087cfbeSBarry Smith MPI_Datatype MPI_C_COMPLEX; 1442c876bd9SBarry Smith #endif 1457087cfbeSBarry Smith PetscScalar PETSC_i; 146e5c89e4eSSatish Balay #else 1477087cfbeSBarry Smith PetscScalar PETSC_i = 0.0; 148e5c89e4eSSatish Balay #endif 149ce63c4c1SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128) 150c90a1750SBarry Smith MPI_Datatype MPIU___FLOAT128 = 0; 151c90a1750SBarry Smith #endif 1527087cfbeSBarry Smith MPI_Datatype MPIU_2SCALAR = 0; 1537087cfbeSBarry Smith MPI_Datatype MPIU_2INT = 0; 15475567043SBarry Smith 155e5c89e4eSSatish Balay /* 156e5c89e4eSSatish Balay These are needed by petscbt.h 157e5c89e4eSSatish Balay */ 158c6db04a5SJed Brown #include <petscbt.h> 1597087cfbeSBarry Smith char _BT_mask = ' '; 1607087cfbeSBarry Smith char _BT_c = ' '; 1617087cfbeSBarry Smith PetscInt _BT_idx = 0; 162e5c89e4eSSatish Balay 163e5c89e4eSSatish Balay /* 164e5c89e4eSSatish Balay Function that is called to display all error messages 165e5c89e4eSSatish Balay */ 1667087cfbeSBarry Smith PetscErrorCode (*PetscErrorPrintf)(const char [],...) = PetscErrorPrintfDefault; 1677087cfbeSBarry Smith PetscErrorCode (*PetscHelpPrintf)(MPI_Comm,const char [],...) = PetscHelpPrintfDefault; 168238ccf28SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE) 1697087cfbeSBarry Smith PetscErrorCode (*PetscVFPrintf)(FILE*,const char[],va_list) = PetscVFPrintf_Matlab; 170238ccf28SShri Abhyankar #else 1717087cfbeSBarry Smith PetscErrorCode (*PetscVFPrintf)(FILE*,const char[],va_list) = PetscVFPrintfDefault; 172238ccf28SShri Abhyankar #endif 173bab1f7e6SVictor Minden /* 1748154be41SBarry Smith This is needed to turn on/off cusp synchronization */ 1758154be41SBarry Smith PetscBool synchronizeCUSP = PETSC_FALSE; 176bab1f7e6SVictor Minden 177e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/ 178e5c89e4eSSatish Balay /* 179e5c89e4eSSatish Balay Optional file where all PETSc output from various prints is saved 180e5c89e4eSSatish Balay */ 181e5c89e4eSSatish Balay FILE *petsc_history = PETSC_NULL; 182e5c89e4eSSatish Balay 183e5c89e4eSSatish Balay #undef __FUNCT__ 184f3dea69dSBarry Smith #define __FUNCT__ "PetscOpenHistoryFile" 1857087cfbeSBarry Smith PetscErrorCode PetscOpenHistoryFile(const char filename[],FILE **fd) 186e5c89e4eSSatish Balay { 187e5c89e4eSSatish Balay PetscErrorCode ierr; 188e5c89e4eSSatish Balay PetscMPIInt rank,size; 189e5c89e4eSSatish Balay char pfile[PETSC_MAX_PATH_LEN],pname[PETSC_MAX_PATH_LEN],fname[PETSC_MAX_PATH_LEN],date[64]; 190e5c89e4eSSatish Balay char version[256]; 191e5c89e4eSSatish Balay 192e5c89e4eSSatish Balay PetscFunctionBegin; 193e5c89e4eSSatish Balay ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); 194e5c89e4eSSatish Balay if (!rank) { 195e5c89e4eSSatish Balay char arch[10]; 196f56c2debSBarry Smith int err; 19788c29154SBarry Smith PetscViewer viewer; 198f56c2debSBarry Smith 199e5c89e4eSSatish Balay ierr = PetscGetArchType(arch,10);CHKERRQ(ierr); 200e5c89e4eSSatish Balay ierr = PetscGetDate(date,64);CHKERRQ(ierr); 201a523d312SBarry Smith ierr = PetscGetVersion(version,256);CHKERRQ(ierr); 202e5c89e4eSSatish Balay ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); 203e5c89e4eSSatish Balay if (filename) { 204e5c89e4eSSatish Balay ierr = PetscFixFilename(filename,fname);CHKERRQ(ierr); 205e5c89e4eSSatish Balay } else { 206e5c89e4eSSatish Balay ierr = PetscGetHomeDirectory(pfile,240);CHKERRQ(ierr); 207e5c89e4eSSatish Balay ierr = PetscStrcat(pfile,"/.petschistory");CHKERRQ(ierr); 208e5c89e4eSSatish Balay ierr = PetscFixFilename(pfile,fname);CHKERRQ(ierr); 209e5c89e4eSSatish Balay } 210e5c89e4eSSatish Balay 211e32f2f54SBarry Smith *fd = fopen(fname,"a"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file: %s",fname); 212e5c89e4eSSatish Balay ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr); 213e5c89e4eSSatish Balay ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"%s %s\n",version,date);CHKERRQ(ierr); 214e5c89e4eSSatish Balay ierr = PetscGetProgramName(pname,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 215e5c89e4eSSatish Balay ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"%s on a %s, %d proc. with options:\n",pname,arch,size);CHKERRQ(ierr); 21688c29154SBarry Smith ierr = PetscViewerASCIIOpenWithFILE(PETSC_COMM_WORLD,*fd,&viewer);CHKERRQ(ierr); 21788c29154SBarry Smith ierr = PetscOptionsView(viewer);CHKERRQ(ierr); 2186bf464f9SBarry Smith ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 219e5c89e4eSSatish Balay ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr); 220f56c2debSBarry Smith err = fflush(*fd); 221e32f2f54SBarry Smith if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 222e5c89e4eSSatish Balay } 223e5c89e4eSSatish Balay PetscFunctionReturn(0); 224e5c89e4eSSatish Balay } 225e5c89e4eSSatish Balay 226e5c89e4eSSatish Balay #undef __FUNCT__ 227f3dea69dSBarry Smith #define __FUNCT__ "PetscCloseHistoryFile" 2287087cfbeSBarry Smith PetscErrorCode PetscCloseHistoryFile(FILE **fd) 229e5c89e4eSSatish Balay { 230e5c89e4eSSatish Balay PetscErrorCode ierr; 231e5c89e4eSSatish Balay PetscMPIInt rank; 232e5c89e4eSSatish Balay char date[64]; 233f56c2debSBarry Smith int err; 234e5c89e4eSSatish Balay 235e5c89e4eSSatish Balay PetscFunctionBegin; 236e5c89e4eSSatish Balay ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); 237e5c89e4eSSatish Balay if (!rank) { 238e5c89e4eSSatish Balay ierr = PetscGetDate(date,64);CHKERRQ(ierr); 239e5c89e4eSSatish Balay ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr); 240e5c89e4eSSatish Balay ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"Finished at %s\n",date);CHKERRQ(ierr); 241e5c89e4eSSatish Balay ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr); 242f56c2debSBarry Smith err = fflush(*fd); 243e32f2f54SBarry Smith if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 244f56c2debSBarry Smith err = fclose(*fd); 245e32f2f54SBarry Smith if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file"); 246e5c89e4eSSatish Balay } 247e5c89e4eSSatish Balay PetscFunctionReturn(0); 248e5c89e4eSSatish Balay } 249e5c89e4eSSatish Balay 250e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/ 251e5c89e4eSSatish Balay 252e5c89e4eSSatish Balay /* 253e5c89e4eSSatish Balay This is ugly and probably belongs somewhere else, but I want to 254e5c89e4eSSatish Balay be able to put a true MPI abort error handler with command line args. 255e5c89e4eSSatish Balay 256e5c89e4eSSatish Balay This is so MPI errors in the debugger will leave all the stack 2573c311c98SBarry Smith frames. The default MP_Abort() cleans up and exits thus providing no useful information 2583c311c98SBarry Smith in the debugger hence we call abort() instead of MPI_Abort(). 259e5c89e4eSSatish Balay */ 260e5c89e4eSSatish Balay 261e5c89e4eSSatish Balay #undef __FUNCT__ 262e5c89e4eSSatish Balay #define __FUNCT__ "Petsc_MPI_AbortOnError" 263e5c89e4eSSatish Balay void Petsc_MPI_AbortOnError(MPI_Comm *comm,PetscMPIInt *flag) 264e5c89e4eSSatish Balay { 265e5c89e4eSSatish Balay PetscFunctionBegin; 2663c311c98SBarry Smith (*PetscErrorPrintf)("MPI error %d\n",*flag); 267e5c89e4eSSatish Balay abort(); 268e5c89e4eSSatish Balay } 269e5c89e4eSSatish Balay 270e5c89e4eSSatish Balay #undef __FUNCT__ 271e5c89e4eSSatish Balay #define __FUNCT__ "Petsc_MPI_DebuggerOnError" 272e5c89e4eSSatish Balay void Petsc_MPI_DebuggerOnError(MPI_Comm *comm,PetscMPIInt *flag) 273e5c89e4eSSatish Balay { 274e5c89e4eSSatish Balay PetscErrorCode ierr; 275e5c89e4eSSatish Balay 276e5c89e4eSSatish Balay PetscFunctionBegin; 2773c311c98SBarry Smith (*PetscErrorPrintf)("MPI error %d\n",*flag); 278e5c89e4eSSatish Balay ierr = PetscAttachDebugger(); 279e5c89e4eSSatish Balay if (ierr) { /* hopeless so get out */ 2803c311c98SBarry Smith MPI_Abort(*comm,*flag); 281e5c89e4eSSatish Balay } 282e5c89e4eSSatish Balay } 283e5c89e4eSSatish Balay 284e5c89e4eSSatish Balay #undef __FUNCT__ 285e5c89e4eSSatish Balay #define __FUNCT__ "PetscEnd" 286e5c89e4eSSatish Balay /*@C 287e5c89e4eSSatish Balay PetscEnd - Calls PetscFinalize() and then ends the program. This is useful if one 288e5c89e4eSSatish Balay wishes a clean exit somewhere deep in the program. 289e5c89e4eSSatish Balay 290e5c89e4eSSatish Balay Collective on PETSC_COMM_WORLD 291e5c89e4eSSatish Balay 292e5c89e4eSSatish Balay Options Database Keys are the same as for PetscFinalize() 293e5c89e4eSSatish Balay 294e5c89e4eSSatish Balay Level: advanced 295e5c89e4eSSatish Balay 296e5c89e4eSSatish Balay Note: 297e5c89e4eSSatish Balay See PetscInitialize() for more general runtime options. 298e5c89e4eSSatish Balay 29988c29154SBarry Smith .seealso: PetscInitialize(), PetscOptionsView(), PetscMallocDump(), PetscMPIDump(), PetscFinalize() 300e5c89e4eSSatish Balay @*/ 3017087cfbeSBarry Smith PetscErrorCode PetscEnd(void) 302e5c89e4eSSatish Balay { 303e5c89e4eSSatish Balay PetscFunctionBegin; 304e5c89e4eSSatish Balay PetscFinalize(); 305e5c89e4eSSatish Balay exit(0); 306e5c89e4eSSatish Balay return 0; 307e5c89e4eSSatish Balay } 308e5c89e4eSSatish Balay 309ace3abfcSBarry Smith PetscBool PetscOptionsPublish = PETSC_FALSE; 31009573ac7SBarry Smith extern PetscErrorCode PetscSetUseTrMalloc_Private(void); 311ace3abfcSBarry Smith extern PetscBool petscsetmallocvisited; 312e5c89e4eSSatish Balay static char emacsmachinename[256]; 313e5c89e4eSSatish Balay 314e5c89e4eSSatish Balay PetscErrorCode (*PetscExternalVersionFunction)(MPI_Comm) = 0; 315e5c89e4eSSatish Balay PetscErrorCode (*PetscExternalHelpFunction)(MPI_Comm) = 0; 316e5c89e4eSSatish Balay 317e5c89e4eSSatish Balay #undef __FUNCT__ 318e5c89e4eSSatish Balay #define __FUNCT__ "PetscSetHelpVersionFunctions" 319e5c89e4eSSatish Balay /*@C 320e5c89e4eSSatish Balay PetscSetHelpVersionFunctions - Sets functions that print help and version information 321e5c89e4eSSatish Balay before the PETSc help and version information is printed. Must call BEFORE PetscInitialize(). 322e5c89e4eSSatish Balay This routine enables a "higher-level" package that uses PETSc to print its messages first. 323e5c89e4eSSatish Balay 324e5c89e4eSSatish Balay Input Parameter: 325e5c89e4eSSatish Balay + help - the help function (may be PETSC_NULL) 326da93591fSBarry Smith - version - the version function (may be PETSC_NULL) 327e5c89e4eSSatish Balay 328e5c89e4eSSatish Balay Level: developer 329e5c89e4eSSatish Balay 330e5c89e4eSSatish Balay Concepts: package help message 331e5c89e4eSSatish Balay 332e5c89e4eSSatish Balay @*/ 3337087cfbeSBarry Smith PetscErrorCode PetscSetHelpVersionFunctions(PetscErrorCode (*help)(MPI_Comm),PetscErrorCode (*version)(MPI_Comm)) 334e5c89e4eSSatish Balay { 335e5c89e4eSSatish Balay PetscFunctionBegin; 336e5c89e4eSSatish Balay PetscExternalHelpFunction = help; 337e5c89e4eSSatish Balay PetscExternalVersionFunction = version; 338e5c89e4eSSatish Balay PetscFunctionReturn(0); 339e5c89e4eSSatish Balay } 340e5c89e4eSSatish Balay 341e5c89e4eSSatish Balay #undef __FUNCT__ 342e5c89e4eSSatish Balay #define __FUNCT__ "PetscOptionsCheckInitial_Private" 3437087cfbeSBarry Smith PetscErrorCode PetscOptionsCheckInitial_Private(void) 344e5c89e4eSSatish Balay { 345e5c89e4eSSatish Balay char string[64],mname[PETSC_MAX_PATH_LEN],*f; 346e5c89e4eSSatish Balay MPI_Comm comm = PETSC_COMM_WORLD; 347ace3abfcSBarry Smith PetscBool flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE,flg4 = PETSC_FALSE,flag,flgz,flgzout; 348e5c89e4eSSatish Balay PetscErrorCode ierr; 349a6d0e24fSJed Brown PetscReal si; 350e5c89e4eSSatish Balay int i; 351e5c89e4eSSatish Balay PetscMPIInt rank; 352e5c89e4eSSatish Balay char version[256]; 353e5c89e4eSSatish Balay 354e5c89e4eSSatish Balay PetscFunctionBegin; 355e5c89e4eSSatish Balay ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); 356e5c89e4eSSatish Balay 357e5c89e4eSSatish Balay /* 358e5c89e4eSSatish Balay Setup the memory management; support for tracing malloc() usage 359e5c89e4eSSatish Balay */ 3608bb29257SSatish Balay ierr = PetscOptionsHasName(PETSC_NULL,"-malloc_log",&flg3);CHKERRQ(ierr); 36181b192fdSBarry Smith #if defined(PETSC_USE_DEBUG) && !defined(PETSC_USE_PTHREAD) 362acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc",&flg1,&flg2);CHKERRQ(ierr); 363e5c89e4eSSatish Balay if ((!flg2 || flg1) && !petscsetmallocvisited) { 364555d055bSBarry Smith #if defined(PETSC_HAVE_VALGRIND) 365555d055bSBarry Smith if (flg2 || !(RUNNING_ON_VALGRIND)) { 366555d055bSBarry Smith /* turn off default -malloc if valgrind is being used */ 367555d055bSBarry Smith #endif 368e5c89e4eSSatish Balay ierr = PetscSetUseTrMalloc_Private();CHKERRQ(ierr); 369555d055bSBarry Smith #if defined(PETSC_HAVE_VALGRIND) 370555d055bSBarry Smith } 371555d055bSBarry Smith #endif 372e5c89e4eSSatish Balay } 373e5c89e4eSSatish Balay #else 374acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_dump",&flg1,PETSC_NULL);CHKERRQ(ierr); 375acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc",&flg2,PETSC_NULL);CHKERRQ(ierr); 376e5c89e4eSSatish Balay if (flg1 || flg2 || flg3) {ierr = PetscSetUseTrMalloc_Private();CHKERRQ(ierr);} 377e5c89e4eSSatish Balay #endif 378e5c89e4eSSatish Balay if (flg3) { 379e5c89e4eSSatish Balay ierr = PetscMallocSetDumpLog();CHKERRQ(ierr); 380e5c89e4eSSatish Balay } 38190d69ab7SBarry Smith flg1 = PETSC_FALSE; 382acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_debug",&flg1,PETSC_NULL);CHKERRQ(ierr); 383e5c89e4eSSatish Balay if (flg1) { 384e5c89e4eSSatish Balay ierr = PetscSetUseTrMalloc_Private();CHKERRQ(ierr); 385e5c89e4eSSatish Balay ierr = PetscMallocDebug(PETSC_TRUE);CHKERRQ(ierr); 386e5c89e4eSSatish Balay } 387e5c89e4eSSatish Balay 38890d69ab7SBarry Smith flg1 = PETSC_FALSE; 389acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_info",&flg1,PETSC_NULL);CHKERRQ(ierr); 3907783f70dSSatish Balay if (!flg1) { 39190d69ab7SBarry Smith flg1 = PETSC_FALSE; 392acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-memory_info",&flg1,PETSC_NULL);CHKERRQ(ierr); 3937783f70dSSatish Balay } 394e5c89e4eSSatish Balay if (flg1) { 395e5c89e4eSSatish Balay ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr); 396e5c89e4eSSatish Balay } 397e5c89e4eSSatish Balay 398e5c89e4eSSatish Balay /* 399e5c89e4eSSatish Balay Set the display variable for graphics 400e5c89e4eSSatish Balay */ 401e5c89e4eSSatish Balay ierr = PetscSetDisplay();CHKERRQ(ierr); 402e5c89e4eSSatish Balay 403e5c89e4eSSatish Balay /* 40451dcc849SKerry Stevens Determine whether user specified maximum number of threads 40551dcc849SKerry Stevens */ 40651dcc849SKerry Stevens ierr = PetscOptionsHasName(PETSC_NULL,"-thread_max",&flg1);CHKERRQ(ierr); 40751dcc849SKerry Stevens if(flg1) { 40851dcc849SKerry Stevens ierr = PetscOptionsGetInt(PETSC_NULL,"-thread_max",&PetscMaxThreads,PETSC_NULL);CHKERRQ(ierr); 40951dcc849SKerry Stevens } 41051dcc849SKerry Stevens 41151dcc849SKerry Stevens /* 41251dcc849SKerry Stevens Determine whether to use thread pool 41351dcc849SKerry Stevens */ 41451dcc849SKerry Stevens ierr = PetscOptionsHasName(PETSC_NULL,"-use_thread_pool",&flg1);CHKERRQ(ierr); 41551dcc849SKerry Stevens if(flg1) { 41651dcc849SKerry Stevens PetscUseThreadPool = PETSC_TRUE; 41751d315f7SKerry Stevens PetscInt N_CORES = get_nprocs(); 41851d315f7SKerry Stevens ThreadCoreAffinity = (int*)malloc(N_CORES*sizeof(int)); 41951d315f7SKerry Stevens char tstr[9]; 42051d315f7SKerry Stevens char tbuf[2]; 42151d315f7SKerry Stevens strcpy(tstr,"-thread"); 42251d315f7SKerry Stevens for(i=0;i<PetscMaxThreads;i++) { 42351d315f7SKerry Stevens ThreadCoreAffinity[i] = i; //default 42451d315f7SKerry Stevens sprintf(tbuf,"%d",i); 42551d315f7SKerry Stevens strcat(tstr,tbuf); 42651d315f7SKerry Stevens ierr = PetscOptionsHasName(PETSC_NULL,tstr,&flg1);CHKERRQ(ierr); 42751d315f7SKerry Stevens if(flg1) { 42851d315f7SKerry Stevens ierr = PetscOptionsGetInt(PETSC_NULL,tstr,&ThreadCoreAffinity[i],PETSC_NULL);CHKERRQ(ierr); 42951d315f7SKerry Stevens ThreadCoreAffinity[i] = ThreadCoreAffinity[i]%N_CORES; //check on the user 43051d315f7SKerry Stevens } 43151d315f7SKerry Stevens tstr[7] = '\0'; 43251d315f7SKerry Stevens } 43351d315f7SKerry Stevens //get the thread pool type 43451d315f7SKerry Stevens PetscInt ipool = 0; 43551d315f7SKerry Stevens ierr = PetscOptionsGetInt(PETSC_NULL,"-pool",&ipool,PETSC_NULL);CHKERRQ(ierr); 43651d315f7SKerry Stevens switch(ipool) { 43751d315f7SKerry Stevens case 1: 43851d315f7SKerry Stevens PetscThreadFunc = &PetscThreadFunc_Tree; 43951d315f7SKerry Stevens PetscThreadInitialize = &PetscThreadInitialize_Tree; 44051d315f7SKerry Stevens PetscThreadFinalize = &PetscThreadFinalize_Tree; 44151d315f7SKerry Stevens MainWait = &MainWait_Tree; 44251d315f7SKerry Stevens MainJob = &MainJob_Tree; 44351d315f7SKerry Stevens break; 44451d315f7SKerry Stevens case 2: 44551d315f7SKerry Stevens PetscThreadFunc = &PetscThreadFunc_Main; 44651d315f7SKerry Stevens PetscThreadInitialize = &PetscThreadInitialize_Main; 44751d315f7SKerry Stevens PetscThreadFinalize = &PetscThreadFinalize_Main; 44851d315f7SKerry Stevens MainWait = &MainWait_Main; 44951d315f7SKerry Stevens MainJob = &MainJob_Main; 45051d315f7SKerry Stevens break; 45151d315f7SKerry Stevens case 3: 45251d315f7SKerry Stevens PetscThreadFunc = &PetscThreadFunc_Chain; 45351d315f7SKerry Stevens PetscThreadInitialize = &PetscThreadInitialize_Chain; 45451d315f7SKerry Stevens PetscThreadFinalize = &PetscThreadFinalize_Chain; 45551d315f7SKerry Stevens MainWait = &MainWait_Chain; 45651d315f7SKerry Stevens MainJob = &MainJob_Chain; 45751d315f7SKerry Stevens break; 45851d315f7SKerry Stevens default: 45951d315f7SKerry Stevens PetscThreadFunc = &PetscThreadFunc_True; 46051d315f7SKerry Stevens PetscThreadInitialize = &PetscThreadInitialize_True; 46151d315f7SKerry Stevens PetscThreadFinalize = &PetscThreadFinalize_True; 46251d315f7SKerry Stevens MainWait = &MainWait_True; 46351d315f7SKerry Stevens MainJob = &MainJob_True; 46451d315f7SKerry Stevens break; 46551d315f7SKerry Stevens } 46651dcc849SKerry Stevens } 467*9e800a48SKerry Stevens else { 468*9e800a48SKerry Stevens //need to define these in the case on 'no threads' or 'thread create/destroy' 469*9e800a48SKerry Stevens //could take any of the above versions 470*9e800a48SKerry Stevens PetscThreadInitialize = &PetscThreadInitialize_True; 471*9e800a48SKerry Stevens PetscThreadFinalize = &PetscThreadFinalize_True; 472*9e800a48SKerry Stevens MainWait = &MainWait_True; 473*9e800a48SKerry Stevens MainJob = &MainJob_True; 474*9e800a48SKerry Stevens } 4750ca81413SKerry Stevens PetscThreadInitialize(PetscMaxThreads); 47651dcc849SKerry Stevens /* 477e5c89e4eSSatish Balay Print the PETSc version information 478e5c89e4eSSatish Balay */ 479e5c89e4eSSatish Balay ierr = PetscOptionsHasName(PETSC_NULL,"-v",&flg1);CHKERRQ(ierr); 480e5c89e4eSSatish Balay ierr = PetscOptionsHasName(PETSC_NULL,"-version",&flg2);CHKERRQ(ierr); 481e5c89e4eSSatish Balay ierr = PetscOptionsHasName(PETSC_NULL,"-help",&flg3);CHKERRQ(ierr); 482e5c89e4eSSatish Balay if (flg1 || flg2 || flg3){ 483e5c89e4eSSatish Balay 484e5c89e4eSSatish Balay /* 485e5c89e4eSSatish Balay Print "higher-level" package version message 486e5c89e4eSSatish Balay */ 487e5c89e4eSSatish Balay if (PetscExternalVersionFunction) { 488e5c89e4eSSatish Balay ierr = (*PetscExternalVersionFunction)(comm);CHKERRQ(ierr); 489e5c89e4eSSatish Balay } 490e5c89e4eSSatish Balay 491a523d312SBarry Smith ierr = PetscGetVersion(version,256);CHKERRQ(ierr); 492e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"--------------------------------------------\ 493e5c89e4eSSatish Balay ------------------------------\n");CHKERRQ(ierr); 494e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"%s\n",version);CHKERRQ(ierr); 495e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"%s",PETSC_AUTHOR_INFO);CHKERRQ(ierr); 496e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"See docs/changes/index.html for recent updates.\n");CHKERRQ(ierr); 49784e42920SBarry Smith ierr = (*PetscHelpPrintf)(comm,"See docs/faq.html for problems.\n");CHKERRQ(ierr); 498e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"See docs/manualpages/index.html for help. \n");CHKERRQ(ierr); 499e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"Libraries linked from %s\n",PETSC_LIB_DIR);CHKERRQ(ierr); 500e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"--------------------------------------------\ 501e5c89e4eSSatish Balay ------------------------------\n");CHKERRQ(ierr); 502e5c89e4eSSatish Balay } 503e5c89e4eSSatish Balay 504e5c89e4eSSatish Balay /* 505e5c89e4eSSatish Balay Print "higher-level" package help message 506e5c89e4eSSatish Balay */ 507e5c89e4eSSatish Balay if (flg3){ 508e5c89e4eSSatish Balay if (PetscExternalHelpFunction) { 509e5c89e4eSSatish Balay ierr = (*PetscExternalHelpFunction)(comm);CHKERRQ(ierr); 510e5c89e4eSSatish Balay } 511e5c89e4eSSatish Balay } 512e5c89e4eSSatish Balay 513e5c89e4eSSatish Balay /* 514e5c89e4eSSatish Balay Setup the error handling 515e5c89e4eSSatish Balay */ 51690d69ab7SBarry Smith flg1 = PETSC_FALSE; 517acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-on_error_abort",&flg1,PETSC_NULL);CHKERRQ(ierr); 518cb9801acSJed Brown if (flg1) { ierr = PetscPushErrorHandler(PetscAbortErrorHandler,0);CHKERRQ(ierr);} 51990d69ab7SBarry Smith flg1 = PETSC_FALSE; 520acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-on_error_mpiabort",&flg1,PETSC_NULL);CHKERRQ(ierr); 521cb9801acSJed Brown if (flg1) { ierr = PetscPushErrorHandler(PetscMPIAbortErrorHandler,0);CHKERRQ(ierr);} 52290d69ab7SBarry Smith flg1 = PETSC_FALSE; 523acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-mpi_return_on_error",&flg1,PETSC_NULL);CHKERRQ(ierr); 524e5c89e4eSSatish Balay if (flg1) { 525e5c89e4eSSatish Balay ierr = MPI_Errhandler_set(comm,MPI_ERRORS_RETURN);CHKERRQ(ierr); 526e5c89e4eSSatish Balay } 52790d69ab7SBarry Smith flg1 = PETSC_FALSE; 528acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-no_signal_handler",&flg1,PETSC_NULL);CHKERRQ(ierr); 529cb9801acSJed Brown if (!flg1) {ierr = PetscPushSignalHandler(PetscDefaultSignalHandler,(void*)0);CHKERRQ(ierr);} 53096cc47afSJed Brown flg1 = PETSC_FALSE; 531acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-fp_trap",&flg1,PETSC_NULL);CHKERRQ(ierr); 53296cc47afSJed Brown if (flg1) {ierr = PetscSetFPTrap(PETSC_FP_TRAP_ON);CHKERRQ(ierr);} 533e5c89e4eSSatish Balay 534e5c89e4eSSatish Balay /* 535e5c89e4eSSatish Balay Setup debugger information 536e5c89e4eSSatish Balay */ 537e5c89e4eSSatish Balay ierr = PetscSetDefaultDebugger();CHKERRQ(ierr); 538e5c89e4eSSatish Balay ierr = PetscOptionsGetString(PETSC_NULL,"-on_error_attach_debugger",string,64,&flg1);CHKERRQ(ierr); 539e5c89e4eSSatish Balay if (flg1) { 540e5c89e4eSSatish Balay MPI_Errhandler err_handler; 541e5c89e4eSSatish Balay 542e5c89e4eSSatish Balay ierr = PetscSetDebuggerFromString(string);CHKERRQ(ierr); 543e5c89e4eSSatish Balay ierr = MPI_Errhandler_create((MPI_Handler_function*)Petsc_MPI_DebuggerOnError,&err_handler);CHKERRQ(ierr); 544e5c89e4eSSatish Balay ierr = MPI_Errhandler_set(comm,err_handler);CHKERRQ(ierr); 545e5c89e4eSSatish Balay ierr = PetscPushErrorHandler(PetscAttachDebuggerErrorHandler,0);CHKERRQ(ierr); 546e5c89e4eSSatish Balay } 5475e96ac45SJed Brown ierr = PetscOptionsGetString(PETSC_NULL,"-debug_terminal",string,64,&flg1);CHKERRQ(ierr); 5485e96ac45SJed Brown if (flg1) { ierr = PetscSetDebugTerminal(string);CHKERRQ(ierr); } 549e5c89e4eSSatish Balay ierr = PetscOptionsGetString(PETSC_NULL,"-start_in_debugger",string,64,&flg1);CHKERRQ(ierr); 550e5c89e4eSSatish Balay ierr = PetscOptionsGetString(PETSC_NULL,"-stop_for_debugger",string,64,&flg2);CHKERRQ(ierr); 551e5c89e4eSSatish Balay if (flg1 || flg2) { 552e5c89e4eSSatish Balay PetscMPIInt size; 553e5c89e4eSSatish Balay PetscInt lsize,*nodes; 554e5c89e4eSSatish Balay MPI_Errhandler err_handler; 555e5c89e4eSSatish Balay /* 556e5c89e4eSSatish Balay we have to make sure that all processors have opened 557e5c89e4eSSatish Balay connections to all other processors, otherwise once the 558e5c89e4eSSatish Balay debugger has stated it is likely to receive a SIGUSR1 559e5c89e4eSSatish Balay and kill the program. 560e5c89e4eSSatish Balay */ 561e5c89e4eSSatish Balay ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); 562e5c89e4eSSatish Balay if (size > 2) { 563533163c2SBarry Smith PetscMPIInt dummy = 0; 564e5c89e4eSSatish Balay MPI_Status status; 565e5c89e4eSSatish Balay for (i=0; i<size; i++) { 566e5c89e4eSSatish Balay if (rank != i) { 567e5c89e4eSSatish Balay ierr = MPI_Send(&dummy,1,MPI_INT,i,109,PETSC_COMM_WORLD);CHKERRQ(ierr); 568e5c89e4eSSatish Balay } 569e5c89e4eSSatish Balay } 570e5c89e4eSSatish Balay for (i=0; i<size; i++) { 571e5c89e4eSSatish Balay if (rank != i) { 572e5c89e4eSSatish Balay ierr = MPI_Recv(&dummy,1,MPI_INT,i,109,PETSC_COMM_WORLD,&status);CHKERRQ(ierr); 573e5c89e4eSSatish Balay } 574e5c89e4eSSatish Balay } 575e5c89e4eSSatish Balay } 576e5c89e4eSSatish Balay /* check if this processor node should be in debugger */ 577e5c89e4eSSatish Balay ierr = PetscMalloc(size*sizeof(PetscInt),&nodes);CHKERRQ(ierr); 578e5c89e4eSSatish Balay lsize = size; 579e5c89e4eSSatish Balay ierr = PetscOptionsGetIntArray(PETSC_NULL,"-debugger_nodes",nodes,&lsize,&flag);CHKERRQ(ierr); 580e5c89e4eSSatish Balay if (flag) { 581e5c89e4eSSatish Balay for (i=0; i<lsize; i++) { 582e5c89e4eSSatish Balay if (nodes[i] == rank) { flag = PETSC_FALSE; break; } 583e5c89e4eSSatish Balay } 584e5c89e4eSSatish Balay } 585e5c89e4eSSatish Balay if (!flag) { 586e5c89e4eSSatish Balay ierr = PetscSetDebuggerFromString(string);CHKERRQ(ierr); 587e5c89e4eSSatish Balay ierr = PetscPushErrorHandler(PetscAbortErrorHandler,0);CHKERRQ(ierr); 588e5c89e4eSSatish Balay if (flg1) { 589e5c89e4eSSatish Balay ierr = PetscAttachDebugger();CHKERRQ(ierr); 590e5c89e4eSSatish Balay } else { 591e5c89e4eSSatish Balay ierr = PetscStopForDebugger();CHKERRQ(ierr); 592e5c89e4eSSatish Balay } 593e5c89e4eSSatish Balay ierr = MPI_Errhandler_create((MPI_Handler_function*)Petsc_MPI_AbortOnError,&err_handler);CHKERRQ(ierr); 594e5c89e4eSSatish Balay ierr = MPI_Errhandler_set(comm,err_handler);CHKERRQ(ierr); 595e5c89e4eSSatish Balay } 596e5c89e4eSSatish Balay ierr = PetscFree(nodes);CHKERRQ(ierr); 597e5c89e4eSSatish Balay } 598e5c89e4eSSatish Balay 599e5c89e4eSSatish Balay ierr = PetscOptionsGetString(PETSC_NULL,"-on_error_emacs",emacsmachinename,128,&flg1);CHKERRQ(ierr); 600cb9801acSJed Brown if (flg1 && !rank) {ierr = PetscPushErrorHandler(PetscEmacsClientErrorHandler,emacsmachinename);CHKERRQ(ierr);} 601e5c89e4eSSatish Balay 60293ba235fSBarry Smith #if defined(PETSC_USE_SOCKET_VIEWER) 60322b84c2fSbcordonn /* 60422b84c2fSbcordonn Activates new sockets for zope if needed 60522b84c2fSbcordonn */ 60684ab5442Sbcordonn ierr = PetscOptionsHasName(PETSC_NULL,"-zope", &flgz);CHKERRQ(ierr); 607d8c6e182Sbcordonn ierr = PetscOptionsHasName(PETSC_NULL,"-nostdout", &flgzout);CHKERRQ(ierr); 6086dc8fec2Sbcordonn if (flgz){ 60922b84c2fSbcordonn int sockfd; 610f1384234SBarry Smith char hostname[256]; 61122b84c2fSbcordonn char username[256]; 6126dc8fec2Sbcordonn int remoteport = 9999; 6139c4c166aSBarry Smith 61484ab5442Sbcordonn ierr = PetscOptionsGetString(PETSC_NULL, "-zope", hostname, 256, &flgz);CHKERRQ(ierr); 61584ab5442Sbcordonn if (!hostname[0]){ 6169c4c166aSBarry Smith ierr = PetscGetHostName(hostname,256);CHKERRQ(ierr); 6179c4c166aSBarry Smith } 61822b84c2fSbcordonn ierr = PetscOpenSocket(hostname, remoteport, &sockfd);CHKERRQ(ierr); 6199c4c166aSBarry Smith ierr = PetscGetUserName(username, 256);CHKERRQ(ierr); 62022b84c2fSbcordonn PETSC_ZOPEFD = fdopen(sockfd, "w"); 62122b84c2fSbcordonn if (flgzout){ 62222b84c2fSbcordonn PETSC_STDOUT = PETSC_ZOPEFD; 623606f100bSbcordonn fprintf(PETSC_STDOUT, "<<<user>>> %s\n",username); 6246dc8fec2Sbcordonn fprintf(PETSC_STDOUT, "<<<start>>>"); 6259c4c166aSBarry Smith } else { 626d8c6e182Sbcordonn fprintf(PETSC_ZOPEFD, "<<<user>>> %s\n",username); 627d8c6e182Sbcordonn fprintf(PETSC_ZOPEFD, "<<<start>>>"); 6289c4c166aSBarry Smith } 6299c4c166aSBarry Smith } 63093ba235fSBarry Smith #endif 631ffc871a5SBarry Smith #if defined(PETSC_USE_SERVER) 632ffc871a5SBarry Smith ierr = PetscOptionsHasName(PETSC_NULL,"-server", &flgz);CHKERRQ(ierr); 633ffc871a5SBarry Smith if (flgz){ 634ffc871a5SBarry Smith PetscInt port = PETSC_DECIDE; 635ffc871a5SBarry Smith ierr = PetscOptionsGetInt(PETSC_NULL,"-server",&port,PETSC_NULL);CHKERRQ(ierr); 636ffc871a5SBarry Smith ierr = PetscWebServe(PETSC_COMM_WORLD,(int)port);CHKERRQ(ierr); 637ffc871a5SBarry Smith } 638ffc871a5SBarry Smith #endif 6396dc8fec2Sbcordonn 640e5c89e4eSSatish Balay /* 641e5c89e4eSSatish Balay Setup profiling and logging 642e5c89e4eSSatish Balay */ 6436cf91177SBarry Smith #if defined (PETSC_USE_INFO) 6448bb29257SSatish Balay { 645e5c89e4eSSatish Balay char logname[PETSC_MAX_PATH_LEN]; logname[0] = 0; 6466cf91177SBarry Smith ierr = PetscOptionsGetString(PETSC_NULL,"-info",logname,250,&flg1);CHKERRQ(ierr); 6478bb29257SSatish Balay if (flg1 && logname[0]) { 648fcc2139eSBarry Smith ierr = PetscInfoAllow(PETSC_TRUE,logname);CHKERRQ(ierr); 6498bb29257SSatish Balay } else if (flg1) { 650fcc2139eSBarry Smith ierr = PetscInfoAllow(PETSC_TRUE,PETSC_NULL);CHKERRQ(ierr); 651e5c89e4eSSatish Balay } 652e5c89e4eSSatish Balay } 653865f6aa8SSatish Balay #endif 654865f6aa8SSatish Balay #if defined(PETSC_USE_LOG) 655865f6aa8SSatish Balay mname[0] = 0; 656f3dea69dSBarry Smith ierr = PetscOptionsGetString(PETSC_NULL,"-history",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); 657865f6aa8SSatish Balay if (flg1) { 658865f6aa8SSatish Balay if (mname[0]) { 659f3dea69dSBarry Smith ierr = PetscOpenHistoryFile(mname,&petsc_history);CHKERRQ(ierr); 660865f6aa8SSatish Balay } else { 661f3dea69dSBarry Smith ierr = PetscOpenHistoryFile(0,&petsc_history);CHKERRQ(ierr); 662865f6aa8SSatish Balay } 663865f6aa8SSatish Balay } 664e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MPE) 66590d69ab7SBarry Smith flg1 = PETSC_FALSE; 666fcfd50ebSBarry Smith ierr = PetscOptionsHasName(PETSC_NULL,"-log_mpe",&flg1);CHKERRQ(ierr); 667e5c89e4eSSatish Balay if (flg1) PetscLogMPEBegin(); 668e5c89e4eSSatish Balay #endif 66990d69ab7SBarry Smith flg1 = PETSC_FALSE; 67090d69ab7SBarry Smith flg2 = PETSC_FALSE; 67190d69ab7SBarry Smith flg3 = PETSC_FALSE; 672acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-log_all",&flg1,PETSC_NULL);CHKERRQ(ierr); 673acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-log",&flg2,PETSC_NULL);CHKERRQ(ierr); 674d44e083bSSatish Balay ierr = PetscOptionsHasName(PETSC_NULL,"-log_summary",&flg3);CHKERRQ(ierr); 6759f7b6320SBarry Smith ierr = PetscOptionsHasName(PETSC_NULL,"-log_summary_python",&flg4);CHKERRQ(ierr); 676e5c89e4eSSatish Balay if (flg1) { ierr = PetscLogAllBegin();CHKERRQ(ierr); } 6779f7b6320SBarry Smith else if (flg2 || flg3 || flg4) { ierr = PetscLogBegin();CHKERRQ(ierr);} 678e5c89e4eSSatish Balay 679e5c89e4eSSatish Balay ierr = PetscOptionsGetString(PETSC_NULL,"-log_trace",mname,250,&flg1);CHKERRQ(ierr); 680e5c89e4eSSatish Balay if (flg1) { 681e5c89e4eSSatish Balay char name[PETSC_MAX_PATH_LEN],fname[PETSC_MAX_PATH_LEN]; 682e5c89e4eSSatish Balay FILE *file; 683e5c89e4eSSatish Balay if (mname[0]) { 684e5c89e4eSSatish Balay sprintf(name,"%s.%d",mname,rank); 685e5c89e4eSSatish Balay ierr = PetscFixFilename(name,fname);CHKERRQ(ierr); 686e5c89e4eSSatish Balay file = fopen(fname,"w"); 687f3dea69dSBarry Smith if (!file) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open trace file: %s",fname); 688e5c89e4eSSatish Balay } else { 689da9f1d6bSBarry Smith file = PETSC_STDOUT; 690e5c89e4eSSatish Balay } 691e5c89e4eSSatish Balay ierr = PetscLogTraceBegin(file);CHKERRQ(ierr); 692e5c89e4eSSatish Balay } 693e5c89e4eSSatish Balay #endif 694e5c89e4eSSatish Balay 695e5c89e4eSSatish Balay /* 696e5c89e4eSSatish Balay Setup building of stack frames for all function calls 697e5c89e4eSSatish Balay */ 69863d6bff0SBarry Smith #if defined(PETSC_USE_DEBUG) && !defined(PETSC_USE_PTHREAD) 699e5c89e4eSSatish Balay ierr = PetscStackCreate();CHKERRQ(ierr); 700e5c89e4eSSatish Balay #endif 701e5c89e4eSSatish Balay 702acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-options_gui",&PetscOptionsPublish,PETSC_NULL);CHKERRQ(ierr); 703e5c89e4eSSatish Balay 704e5c89e4eSSatish Balay /* 705e5c89e4eSSatish Balay Print basic help message 706e5c89e4eSSatish Balay */ 707e5c89e4eSSatish Balay ierr = PetscOptionsHasName(PETSC_NULL,"-help",&flg1);CHKERRQ(ierr); 708e5c89e4eSSatish Balay if (flg1) { 709e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"Options for all PETSc programs:\n");CHKERRQ(ierr); 710301d30feSBarry Smith ierr = (*PetscHelpPrintf)(comm," -help: prints help method for each option\n");CHKERRQ(ierr); 711301d30feSBarry Smith ierr = (*PetscHelpPrintf)(comm," -on_error_abort: cause an abort when an error is detected. Useful \n ");CHKERRQ(ierr); 712301d30feSBarry Smith ierr = (*PetscHelpPrintf)(comm," only when run in the debugger\n");CHKERRQ(ierr); 713e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -on_error_attach_debugger [gdb,dbx,xxgdb,ups,noxterm]\n");CHKERRQ(ierr); 714e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," start the debugger in new xterm\n");CHKERRQ(ierr); 715e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," unless noxterm is given\n");CHKERRQ(ierr); 716e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -start_in_debugger [gdb,dbx,xxgdb,ups,noxterm]\n");CHKERRQ(ierr); 717e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," start all processes in the debugger\n");CHKERRQ(ierr); 718e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -on_error_emacs <machinename>\n");CHKERRQ(ierr); 719e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," emacs jumps to error file\n");CHKERRQ(ierr); 720e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -debugger_nodes [n1,n2,..] Nodes to start in debugger\n");CHKERRQ(ierr); 721e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -debugger_pause [m] : delay (in seconds) to attach debugger\n");CHKERRQ(ierr); 722e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -stop_for_debugger : prints message on how to attach debugger manually\n");CHKERRQ(ierr); 723e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," waits the delay for you to attach\n");CHKERRQ(ierr); 724e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -display display: Location where graphics and debuggers are displayed\n");CHKERRQ(ierr); 725e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -no_signal_handler: do not trap error signals\n");CHKERRQ(ierr); 726e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -mpi_return_on_error: MPI returns error code, rather than abort on internal error\n");CHKERRQ(ierr); 727e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -fp_trap: stop on floating point exceptions\n");CHKERRQ(ierr); 728e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," note on IBM RS6000 this slows run greatly\n");CHKERRQ(ierr); 729e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -malloc_dump <optional filename>: dump list of unfreed memory at conclusion\n");CHKERRQ(ierr); 730e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -malloc: use our error checking malloc\n");CHKERRQ(ierr); 731e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -malloc no: don't use error checking malloc\n");CHKERRQ(ierr); 7324161f2a3SBarry Smith ierr = (*PetscHelpPrintf)(comm," -malloc_info: prints total memory usage\n");CHKERRQ(ierr); 7334161f2a3SBarry Smith ierr = (*PetscHelpPrintf)(comm," -malloc_log: keeps log of all memory allocations\n");CHKERRQ(ierr); 734e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -malloc_debug: enables extended checking for memory corruption\n");CHKERRQ(ierr); 735e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -options_table: dump list of options inputted\n");CHKERRQ(ierr); 736e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -options_left: dump list of unused options\n");CHKERRQ(ierr); 737e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -options_left no: don't dump list of unused options\n");CHKERRQ(ierr); 738e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -tmp tmpdir: alternative /tmp directory\n");CHKERRQ(ierr); 739e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -shared_tmp: tmp directory is shared by all processors\n");CHKERRQ(ierr); 740a8c7a070SBarry Smith ierr = (*PetscHelpPrintf)(comm," -not_shared_tmp: each processor has separate tmp directory\n");CHKERRQ(ierr); 741e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -memory_info: print memory usage at end of run\n");CHKERRQ(ierr); 742e5c89e4eSSatish Balay #if defined(PETSC_USE_LOG) 743e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -get_total_flops: total flops over all processors\n");CHKERRQ(ierr); 744e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -log[_all _summary]: logging objects and events\n");CHKERRQ(ierr); 745e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -log_trace [filename]: prints trace of all PETSc calls\n");CHKERRQ(ierr); 746e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MPE) 747e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -log_mpe: Also create logfile viewable through upshot\n");CHKERRQ(ierr); 748e5c89e4eSSatish Balay #endif 7496cf91177SBarry Smith ierr = (*PetscHelpPrintf)(comm," -info <optional filename>: print informative messages about the calculations\n");CHKERRQ(ierr); 750e5c89e4eSSatish Balay #endif 751e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -v: prints PETSc version number and release date\n");CHKERRQ(ierr); 752e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -options_file <file>: reads options from file\n");CHKERRQ(ierr); 753e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm," -petsc_sleep n: sleeps n seconds before running program\n");CHKERRQ(ierr); 754e5c89e4eSSatish Balay ierr = (*PetscHelpPrintf)(comm,"-----------------------------------------------\n");CHKERRQ(ierr); 755e5c89e4eSSatish Balay } 756e5c89e4eSSatish Balay 757a6d0e24fSJed Brown ierr = PetscOptionsGetReal(PETSC_NULL,"-petsc_sleep",&si,&flg1);CHKERRQ(ierr); 758e5c89e4eSSatish Balay if (flg1) { 759e5c89e4eSSatish Balay ierr = PetscSleep(si);CHKERRQ(ierr); 760e5c89e4eSSatish Balay } 761e5c89e4eSSatish Balay 7626cf91177SBarry Smith ierr = PetscOptionsGetString(PETSC_NULL,"-info_exclude",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); 763e5c89e4eSSatish Balay ierr = PetscStrstr(mname,"null",&f);CHKERRQ(ierr); 764e5c89e4eSSatish Balay if (f) { 7656cf91177SBarry Smith ierr = PetscInfoDeactivateClass(PETSC_NULL);CHKERRQ(ierr); 766e5c89e4eSSatish Balay } 767827f890bSBarry Smith 7688154be41SBarry Smith #if defined(PETSC_HAVE_CUSP) 769c97f9302SBarry Smith ierr = PetscOptionsHasName(PETSC_NULL,"-log_summary",&flg3);CHKERRQ(ierr); 77073113deaSBarry Smith if (flg3) flg1 = PETSC_TRUE; 77173113deaSBarry Smith else flg1 = PETSC_FALSE; 7728154be41SBarry Smith ierr = PetscOptionsGetBool(PETSC_NULL,"-cusp_synchronize",&flg1,PETSC_NULL);CHKERRQ(ierr); 7738154be41SBarry Smith if (flg1) synchronizeCUSP = PETSC_TRUE; 774bab1f7e6SVictor Minden #endif 775192daf7cSBarry Smith 776e5c89e4eSSatish Balay PetscFunctionReturn(0); 777e5c89e4eSSatish Balay } 778df413903SBarry Smith 77951d315f7SKerry Stevens /**** 'Tree' Thread Pool Functions ****/ 78051d315f7SKerry Stevens void* PetscThreadFunc_Tree(void* arg) { 78151d315f7SKerry Stevens PetscErrorCode iterr; 78251d315f7SKerry Stevens int icorr,ierr; 78351d315f7SKerry Stevens int* pId = (int*)arg; 78451d315f7SKerry Stevens int ThreadId = *pId,Mary = 2,i,SubWorker; 78551d315f7SKerry Stevens PetscBool PeeOn; 78651d315f7SKerry Stevens cpu_set_t mset; 787*9e800a48SKerry Stevens //printf("Thread %d In Tree Thread Function\n",ThreadId); 78851d315f7SKerry Stevens icorr = ThreadCoreAffinity[ThreadId]; 78951d315f7SKerry Stevens CPU_ZERO(&mset); 79051d315f7SKerry Stevens CPU_SET(icorr,&mset); 79151d315f7SKerry Stevens sched_setaffinity(0,sizeof(cpu_set_t),&mset); 79251d315f7SKerry Stevens 79351d315f7SKerry Stevens if((Mary*ThreadId+1)>(PetscMaxThreads-1)) { 79451d315f7SKerry Stevens PeeOn = PETSC_TRUE; 79551d315f7SKerry Stevens } 79651d315f7SKerry Stevens else { 79751d315f7SKerry Stevens PeeOn = PETSC_FALSE; 79851d315f7SKerry Stevens } 79951d315f7SKerry Stevens if(PeeOn==PETSC_FALSE) { 80051d315f7SKerry Stevens //check your subordinates, wait for them to be ready 80151d315f7SKerry Stevens for(i=1;i<=Mary;i++) { 80251d315f7SKerry Stevens SubWorker = Mary*ThreadId+i; 80351d315f7SKerry Stevens if(SubWorker<PetscMaxThreads) { 80451d315f7SKerry Stevens ierr = pthread_mutex_lock(job_tree.mutexarray[SubWorker]); 80551d315f7SKerry Stevens while(*(job_tree.arrThreadReady[SubWorker])==PETSC_FALSE) { 80651d315f7SKerry Stevens //upon entry, automically releases the lock and blocks 80751d315f7SKerry Stevens //upon return, has the lock 80851d315f7SKerry Stevens ierr = pthread_cond_wait(job_tree.cond1array[SubWorker],job_tree.mutexarray[SubWorker]); 80951d315f7SKerry Stevens } 81051d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_tree.mutexarray[SubWorker]); 81151d315f7SKerry Stevens } 81251d315f7SKerry Stevens } 81351d315f7SKerry Stevens //your subordinates are now ready 81451d315f7SKerry Stevens } 81551d315f7SKerry Stevens ierr = pthread_mutex_lock(job_tree.mutexarray[ThreadId]); 81651d315f7SKerry Stevens //update your ready status 81751d315f7SKerry Stevens *(job_tree.arrThreadReady[ThreadId]) = PETSC_TRUE; 81851d315f7SKerry Stevens if(ThreadId==0) { 81951d315f7SKerry Stevens job_tree.eJobStat = JobCompleted; 82051d315f7SKerry Stevens //signal main 82151d315f7SKerry Stevens ierr = pthread_cond_signal(&main_cond); 82251d315f7SKerry Stevens } 82351d315f7SKerry Stevens else { 82451d315f7SKerry Stevens //tell your boss that you're ready to work 82551d315f7SKerry Stevens ierr = pthread_cond_signal(job_tree.cond1array[ThreadId]); 82651d315f7SKerry Stevens } 82751d315f7SKerry Stevens //the while loop needs to have an exit 82851d315f7SKerry Stevens //the 'main' thread can terminate all the threads by performing a broadcast 82951d315f7SKerry Stevens //and calling FuncFinish 83051d315f7SKerry Stevens while(PetscThreadGo) { 83151d315f7SKerry Stevens //need to check the condition to ensure we don't have to wait 83251d315f7SKerry Stevens //waiting when you don't have to causes problems 83351d315f7SKerry Stevens //also need to check the condition to ensure proper handling of spurious wakeups 83451d315f7SKerry Stevens while(*(job_tree.arrThreadReady[ThreadId])==PETSC_TRUE) { 83551d315f7SKerry Stevens //upon entry, automically releases the lock and blocks 83651d315f7SKerry Stevens //upon return, has the lock 83751d315f7SKerry Stevens ierr = pthread_cond_wait(job_tree.cond2array[ThreadId],job_tree.mutexarray[ThreadId]); 83851d315f7SKerry Stevens *(job_tree.arrThreadStarted[ThreadId]) = PETSC_TRUE; 83951d315f7SKerry Stevens *(job_tree.arrThreadReady[ThreadId]) = PETSC_FALSE; 84051d315f7SKerry Stevens } 84151d315f7SKerry Stevens if(ThreadId==0) { 84251d315f7SKerry Stevens job_tree.startJob = PETSC_FALSE; 84351d315f7SKerry Stevens job_tree.eJobStat = ThreadsWorking; 84451d315f7SKerry Stevens } 84551d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_tree.mutexarray[ThreadId]); 84651d315f7SKerry Stevens if(PeeOn==PETSC_FALSE) { 84751d315f7SKerry Stevens //tell your subordinates it's time to get to work 84851d315f7SKerry Stevens for(i=1; i<=Mary; i++) { 84951d315f7SKerry Stevens SubWorker = Mary*ThreadId+i; 85051d315f7SKerry Stevens if(SubWorker<PetscMaxThreads) { 85151d315f7SKerry Stevens ierr = pthread_cond_signal(job_tree.cond2array[SubWorker]); 85251d315f7SKerry Stevens } 85351d315f7SKerry Stevens } 85451d315f7SKerry Stevens } 85551d315f7SKerry Stevens //do your job 85651d315f7SKerry Stevens if(job_tree.pdata==NULL) { 85751d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_tree.pfunc(job_tree.pdata); 85851d315f7SKerry Stevens } 85951d315f7SKerry Stevens else { 86051d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_tree.pfunc(job_tree.pdata[ThreadId]); 86151d315f7SKerry Stevens } 86251d315f7SKerry Stevens if(iterr!=0) { 86351d315f7SKerry Stevens ithreaderr = 1; 86451d315f7SKerry Stevens } 86551d315f7SKerry Stevens if(PetscThreadGo) { 86651d315f7SKerry Stevens //reset job, get ready for more 86751d315f7SKerry Stevens if(PeeOn==PETSC_FALSE) { 86851d315f7SKerry Stevens //check your subordinates, waiting for them to be ready 86951d315f7SKerry Stevens //how do you know for a fact that a given subordinate has actually started? 87051d315f7SKerry Stevens for(i=1;i<=Mary;i++) { 87151d315f7SKerry Stevens SubWorker = Mary*ThreadId+i; 87251d315f7SKerry Stevens if(SubWorker<PetscMaxThreads) { 87351d315f7SKerry Stevens ierr = pthread_mutex_lock(job_tree.mutexarray[SubWorker]); 87451d315f7SKerry Stevens while(*(job_tree.arrThreadReady[SubWorker])==PETSC_FALSE||*(job_tree.arrThreadStarted[SubWorker])==PETSC_FALSE) { 87551d315f7SKerry Stevens //upon entry, automically releases the lock and blocks 87651d315f7SKerry Stevens //upon return, has the lock 87751d315f7SKerry Stevens ierr = pthread_cond_wait(job_tree.cond1array[SubWorker],job_tree.mutexarray[SubWorker]); 87851d315f7SKerry Stevens } 87951d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_tree.mutexarray[SubWorker]); 88051d315f7SKerry Stevens } 88151d315f7SKerry Stevens } 88251d315f7SKerry Stevens //your subordinates are now ready 88351d315f7SKerry Stevens } 88451d315f7SKerry Stevens ierr = pthread_mutex_lock(job_tree.mutexarray[ThreadId]); 88551d315f7SKerry Stevens *(job_tree.arrThreadReady[ThreadId]) = PETSC_TRUE; 88651d315f7SKerry Stevens if(ThreadId==0) { 88751d315f7SKerry Stevens job_tree.eJobStat = JobCompleted; //root thread: last thread to complete, guaranteed! 88851d315f7SKerry Stevens //root thread signals 'main' 88951d315f7SKerry Stevens ierr = pthread_cond_signal(&main_cond); 89051d315f7SKerry Stevens } 89151d315f7SKerry Stevens else { 89251d315f7SKerry Stevens //signal your boss before you go to sleep 89351d315f7SKerry Stevens ierr = pthread_cond_signal(job_tree.cond1array[ThreadId]); 89451d315f7SKerry Stevens } 89551d315f7SKerry Stevens } 89651d315f7SKerry Stevens } 89751d315f7SKerry Stevens return NULL; 89851d315f7SKerry Stevens } 89951d315f7SKerry Stevens 90051d315f7SKerry Stevens #undef __FUNCT__ 90151d315f7SKerry Stevens #define __FUNCT__ "PetscThreadInitialize_Tree" 90251d315f7SKerry Stevens void* PetscThreadInitialize_Tree(PetscInt N) { 90351d315f7SKerry Stevens PetscInt i,ierr; 90451d315f7SKerry Stevens int status; 90551d315f7SKerry Stevens 90651d315f7SKerry Stevens if(PetscUseThreadPool) { 90751d315f7SKerry Stevens size_t Val1 = (size_t)CACHE_LINE_SIZE; 90851d315f7SKerry Stevens size_t Val2 = (size_t)PetscMaxThreads*CACHE_LINE_SIZE; 90951d315f7SKerry Stevens arrmutex = (char*)memalign(Val1,Val2); 91051d315f7SKerry Stevens arrcond1 = (char*)memalign(Val1,Val2); 91151d315f7SKerry Stevens arrcond2 = (char*)memalign(Val1,Val2); 91251d315f7SKerry Stevens arrstart = (char*)memalign(Val1,Val2); 91351d315f7SKerry Stevens arrready = (char*)memalign(Val1,Val2); 91451d315f7SKerry Stevens job_tree.mutexarray = (pthread_mutex_t**)malloc(PetscMaxThreads*sizeof(pthread_mutex_t*)); 91551d315f7SKerry Stevens job_tree.cond1array = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*)); 91651d315f7SKerry Stevens job_tree.cond2array = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*)); 91751d315f7SKerry Stevens job_tree.arrThreadStarted = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*)); 91851d315f7SKerry Stevens job_tree.arrThreadReady = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*)); 91951d315f7SKerry Stevens //initialize job structure 92051d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 92151d315f7SKerry Stevens job_tree.mutexarray[i] = (pthread_mutex_t*)(arrmutex+CACHE_LINE_SIZE*i); 92251d315f7SKerry Stevens job_tree.cond1array[i] = (pthread_cond_t*)(arrcond1+CACHE_LINE_SIZE*i); 92351d315f7SKerry Stevens job_tree.cond2array[i] = (pthread_cond_t*)(arrcond2+CACHE_LINE_SIZE*i); 92451d315f7SKerry Stevens job_tree.arrThreadStarted[i] = (PetscBool*)(arrstart+CACHE_LINE_SIZE*i); 92551d315f7SKerry Stevens job_tree.arrThreadReady[i] = (PetscBool*)(arrready+CACHE_LINE_SIZE*i); 92651d315f7SKerry Stevens } 92751d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 92851d315f7SKerry Stevens ierr = pthread_mutex_init(job_tree.mutexarray[i],NULL); 92951d315f7SKerry Stevens ierr = pthread_cond_init(job_tree.cond1array[i],NULL); 93051d315f7SKerry Stevens ierr = pthread_cond_init(job_tree.cond2array[i],NULL); 93151d315f7SKerry Stevens *(job_tree.arrThreadStarted[i]) = PETSC_FALSE; 93251d315f7SKerry Stevens *(job_tree.arrThreadReady[i]) = PETSC_FALSE; 93351d315f7SKerry Stevens } 93451d315f7SKerry Stevens job_tree.pfunc = NULL; 93551d315f7SKerry Stevens job_tree.pdata = (void**)malloc(N*sizeof(void*)); 93651d315f7SKerry Stevens job_tree.startJob = PETSC_FALSE; 93751d315f7SKerry Stevens job_tree.eJobStat = JobInitiated; 93851d315f7SKerry Stevens pVal = (int*)malloc(N*sizeof(int)); 93951d315f7SKerry Stevens //allocate memory in the heap for the thread structure 94051d315f7SKerry Stevens PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t)); 94151d315f7SKerry Stevens //create threads 94251d315f7SKerry Stevens for(i=0; i<N; i++) { 94351d315f7SKerry Stevens pVal[i] = i; 94451d315f7SKerry Stevens status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]); 94551d315f7SKerry Stevens //error check 94651d315f7SKerry Stevens } 94751d315f7SKerry Stevens } 94851d315f7SKerry Stevens else { 94951d315f7SKerry Stevens //do nothing 95051d315f7SKerry Stevens } 95151d315f7SKerry Stevens return NULL; 95251d315f7SKerry Stevens } 95351d315f7SKerry Stevens 95451d315f7SKerry Stevens #undef __FUNCT__ 95551d315f7SKerry Stevens #define __FUNCT__ "PetscThreadFinalize_Tree" 95651d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Tree() { 95751d315f7SKerry Stevens int i,ierr; 95851d315f7SKerry Stevens void* jstatus; 95951d315f7SKerry Stevens 96051d315f7SKerry Stevens PetscFunctionBegin; 96151d315f7SKerry Stevens 96251d315f7SKerry Stevens if(PetscUseThreadPool) { 96351d315f7SKerry Stevens MainJob(FuncFinish,NULL,PetscMaxThreads); //set up job and broadcast work 96451d315f7SKerry Stevens //join the threads 96551d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 96651d315f7SKerry Stevens ierr = pthread_join(PetscThreadPoint[i],&jstatus); 96751d315f7SKerry Stevens //do error checking 96851d315f7SKerry Stevens } 96951d315f7SKerry Stevens free(PetscThreadPoint); 97051d315f7SKerry Stevens free(arrmutex); 97151d315f7SKerry Stevens free(arrcond1); 97251d315f7SKerry Stevens free(arrcond2); 97351d315f7SKerry Stevens free(arrstart); 97451d315f7SKerry Stevens free(arrready); 97551d315f7SKerry Stevens free(job_tree.pdata); 97651d315f7SKerry Stevens free(pVal); 97751d315f7SKerry Stevens } 97851d315f7SKerry Stevens else { 97951d315f7SKerry Stevens } 98051d315f7SKerry Stevens PetscFunctionReturn(0); 98151d315f7SKerry Stevens } 98251d315f7SKerry Stevens 98351d315f7SKerry Stevens #undef __FUNCT__ 98451d315f7SKerry Stevens #define __FUNCT__ "MainWait_Tree" 98551d315f7SKerry Stevens void MainWait_Tree() { 98651d315f7SKerry Stevens int ierr; 98751d315f7SKerry Stevens ierr = pthread_mutex_lock(job_tree.mutexarray[0]); 98851d315f7SKerry Stevens while(job_tree.eJobStat<JobCompleted||job_tree.startJob==PETSC_TRUE) { 98951d315f7SKerry Stevens ierr = pthread_cond_wait(&main_cond,job_tree.mutexarray[0]); 99051d315f7SKerry Stevens } 99151d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_tree.mutexarray[0]); 99251d315f7SKerry Stevens } 99351d315f7SKerry Stevens 99451d315f7SKerry Stevens #undef __FUNCT__ 99551d315f7SKerry Stevens #define __FUNCT__ "MainJob_Tree" 99651d315f7SKerry Stevens PetscErrorCode MainJob_Tree(void* (*pFunc)(void*),void** data,PetscInt n) { 99751d315f7SKerry Stevens int i,ierr; 99851d315f7SKerry Stevens PetscErrorCode ijoberr = 0; 99951d315f7SKerry Stevens if(PetscUseThreadPool) { 100051d315f7SKerry Stevens MainWait(); 100151d315f7SKerry Stevens job_tree.pfunc = pFunc; 100251d315f7SKerry Stevens job_tree.pdata = data; 100351d315f7SKerry Stevens job_tree.startJob = PETSC_TRUE; 100451d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 100551d315f7SKerry Stevens *(job_tree.arrThreadStarted[i]) = PETSC_FALSE; 100651d315f7SKerry Stevens } 100751d315f7SKerry Stevens job_tree.eJobStat = JobInitiated; 100851d315f7SKerry Stevens ierr = pthread_cond_signal(job_tree.cond2array[0]); 100951d315f7SKerry Stevens if(pFunc!=FuncFinish) { 101051d315f7SKerry Stevens MainWait(); //why wait after? guarantees that job gets done before proceeding with result collection (if any) 101151d315f7SKerry Stevens } 101251d315f7SKerry Stevens } 101351d315f7SKerry Stevens else { 101451d315f7SKerry Stevens pthread_t* apThread = (pthread_t*)malloc(n*sizeof(pthread_t)); 101551d315f7SKerry Stevens PetscThreadRun(MPI_COMM_WORLD,pFunc,n,apThread,data); 101651d315f7SKerry Stevens PetscThreadStop(MPI_COMM_WORLD,n,apThread); //ensures that all threads are finished with the job 101751d315f7SKerry Stevens free(apThread); 101851d315f7SKerry Stevens } 101951d315f7SKerry Stevens if(ithreaderr) { 102051d315f7SKerry Stevens ijoberr = ithreaderr; 102151d315f7SKerry Stevens } 102251d315f7SKerry Stevens return ijoberr; 102351d315f7SKerry Stevens } 102451d315f7SKerry Stevens /**** ****/ 102551d315f7SKerry Stevens 102651d315f7SKerry Stevens /**** 'Main' Thread Pool Functions ****/ 102751d315f7SKerry Stevens void* PetscThreadFunc_Main(void* arg) { 102851d315f7SKerry Stevens PetscErrorCode iterr; 102951d315f7SKerry Stevens int icorr,ierr; 103051d315f7SKerry Stevens int* pId = (int*)arg; 103151d315f7SKerry Stevens int ThreadId = *pId; 103251d315f7SKerry Stevens cpu_set_t mset; 1033*9e800a48SKerry Stevens //printf("Thread %d In Main Thread Function\n",ThreadId); 103451d315f7SKerry Stevens icorr = ThreadCoreAffinity[ThreadId]; 103551d315f7SKerry Stevens CPU_ZERO(&mset); 103651d315f7SKerry Stevens CPU_SET(icorr,&mset); 103751d315f7SKerry Stevens sched_setaffinity(0,sizeof(cpu_set_t),&mset); 103851d315f7SKerry Stevens 103951d315f7SKerry Stevens ierr = pthread_mutex_lock(job_main.mutexarray[ThreadId]); 104051d315f7SKerry Stevens //update your ready status 104151d315f7SKerry Stevens *(job_main.arrThreadReady[ThreadId]) = PETSC_TRUE; 104251d315f7SKerry Stevens //tell the BOSS that you're ready to work before you go to sleep 104351d315f7SKerry Stevens ierr = pthread_cond_signal(job_main.cond1array[ThreadId]); 104451d315f7SKerry Stevens 104551d315f7SKerry Stevens //the while loop needs to have an exit 104651d315f7SKerry Stevens //the 'main' thread can terminate all the threads by performing a broadcast 104751d315f7SKerry Stevens //and calling FuncFinish 104851d315f7SKerry Stevens while(PetscThreadGo) { 104951d315f7SKerry Stevens //need to check the condition to ensure we don't have to wait 105051d315f7SKerry Stevens //waiting when you don't have to causes problems 105151d315f7SKerry Stevens //also need to check the condition to ensure proper handling of spurious wakeups 105251d315f7SKerry Stevens while(*(job_main.arrThreadReady[ThreadId])==PETSC_TRUE) { 105351d315f7SKerry Stevens //upon entry, atomically releases the lock and blocks 105451d315f7SKerry Stevens //upon return, has the lock 105551d315f7SKerry Stevens ierr = pthread_cond_wait(job_main.cond2array[ThreadId],job_main.mutexarray[ThreadId]); 105651d315f7SKerry Stevens //*(job_main.arrThreadReady[ThreadId]) = PETSC_FALSE; 105751d315f7SKerry Stevens } 105851d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_main.mutexarray[ThreadId]); 105951d315f7SKerry Stevens //do your job 106051d315f7SKerry Stevens if(job_main.pdata==NULL) { 106151d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_main.pfunc(job_main.pdata); 106251d315f7SKerry Stevens } 106351d315f7SKerry Stevens else { 106451d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_main.pfunc(job_main.pdata[ThreadId]); 106551d315f7SKerry Stevens } 106651d315f7SKerry Stevens if(iterr!=0) { 106751d315f7SKerry Stevens ithreaderr = 1; 106851d315f7SKerry Stevens } 106951d315f7SKerry Stevens if(PetscThreadGo) { 107051d315f7SKerry Stevens //reset job, get ready for more 107151d315f7SKerry Stevens ierr = pthread_mutex_lock(job_main.mutexarray[ThreadId]); 107251d315f7SKerry Stevens *(job_main.arrThreadReady[ThreadId]) = PETSC_TRUE; 107351d315f7SKerry Stevens //tell the BOSS that you're ready to work before you go to sleep 107451d315f7SKerry Stevens ierr = pthread_cond_signal(job_main.cond1array[ThreadId]); 107551d315f7SKerry Stevens } 107651d315f7SKerry Stevens } 107751d315f7SKerry Stevens return NULL; 107851d315f7SKerry Stevens } 107951d315f7SKerry Stevens 108051d315f7SKerry Stevens #undef __FUNCT__ 108151d315f7SKerry Stevens #define __FUNCT__ "PetscThreadInitialize_Main" 108251d315f7SKerry Stevens void* PetscThreadInitialize_Main(PetscInt N) { 108351d315f7SKerry Stevens PetscInt i,ierr; 108451d315f7SKerry Stevens int status; 108551d315f7SKerry Stevens 108651d315f7SKerry Stevens if(PetscUseThreadPool) { 108751d315f7SKerry Stevens size_t Val1 = (size_t)CACHE_LINE_SIZE; 108851d315f7SKerry Stevens size_t Val2 = (size_t)PetscMaxThreads*CACHE_LINE_SIZE; 108951d315f7SKerry Stevens arrmutex = (char*)memalign(Val1,Val2); 109051d315f7SKerry Stevens arrcond1 = (char*)memalign(Val1,Val2); 109151d315f7SKerry Stevens arrcond2 = (char*)memalign(Val1,Val2); 109251d315f7SKerry Stevens arrstart = (char*)memalign(Val1,Val2); 109351d315f7SKerry Stevens arrready = (char*)memalign(Val1,Val2); 109451d315f7SKerry Stevens job_main.mutexarray = (pthread_mutex_t**)malloc(PetscMaxThreads*sizeof(pthread_mutex_t*)); 109551d315f7SKerry Stevens job_main.cond1array = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*)); 109651d315f7SKerry Stevens job_main.cond2array = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*)); 109751d315f7SKerry Stevens job_main.arrThreadReady = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*)); 109851d315f7SKerry Stevens //initialize job structure 109951d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 110051d315f7SKerry Stevens job_main.mutexarray[i] = (pthread_mutex_t*)(arrmutex+CACHE_LINE_SIZE*i); 110151d315f7SKerry Stevens job_main.cond1array[i] = (pthread_cond_t*)(arrcond1+CACHE_LINE_SIZE*i); 110251d315f7SKerry Stevens job_main.cond2array[i] = (pthread_cond_t*)(arrcond2+CACHE_LINE_SIZE*i); 110351d315f7SKerry Stevens job_main.arrThreadReady[i] = (PetscBool*)(arrready+CACHE_LINE_SIZE*i); 110451d315f7SKerry Stevens } 110551d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 110651d315f7SKerry Stevens ierr = pthread_mutex_init(job_main.mutexarray[i],NULL); 110751d315f7SKerry Stevens ierr = pthread_cond_init(job_main.cond1array[i],NULL); 110851d315f7SKerry Stevens ierr = pthread_cond_init(job_main.cond2array[i],NULL); 110951d315f7SKerry Stevens *(job_main.arrThreadReady[i]) = PETSC_FALSE; 111051d315f7SKerry Stevens } 111151d315f7SKerry Stevens job_main.pfunc = NULL; 111251d315f7SKerry Stevens job_main.pdata = (void**)malloc(N*sizeof(void*)); 111351d315f7SKerry Stevens pVal = (int*)malloc(N*sizeof(int)); 111451d315f7SKerry Stevens //allocate memory in the heap for the thread structure 111551d315f7SKerry Stevens PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t)); 111651d315f7SKerry Stevens //create threads 111751d315f7SKerry Stevens for(i=0; i<N; i++) { 111851d315f7SKerry Stevens pVal[i] = i; 111951d315f7SKerry Stevens status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]); 112051d315f7SKerry Stevens //error check 112151d315f7SKerry Stevens } 112251d315f7SKerry Stevens } 112351d315f7SKerry Stevens else { 112451d315f7SKerry Stevens } 112551d315f7SKerry Stevens return NULL; 112651d315f7SKerry Stevens } 112751d315f7SKerry Stevens 112851d315f7SKerry Stevens #undef __FUNCT__ 112951d315f7SKerry Stevens #define __FUNCT__ "PetscThreadFinalize_Main" 113051d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Main() { 113151d315f7SKerry Stevens int i,ierr; 113251d315f7SKerry Stevens void* jstatus; 113351d315f7SKerry Stevens 113451d315f7SKerry Stevens PetscFunctionBegin; 113551d315f7SKerry Stevens 113651d315f7SKerry Stevens if(PetscUseThreadPool) { 113751d315f7SKerry Stevens MainJob(FuncFinish,NULL,PetscMaxThreads); //set up job and broadcast work 113851d315f7SKerry Stevens //join the threads 113951d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 114051d315f7SKerry Stevens ierr = pthread_join(PetscThreadPoint[i],&jstatus); 114151d315f7SKerry Stevens //do error checking 114251d315f7SKerry Stevens } 114351d315f7SKerry Stevens free(PetscThreadPoint); 114451d315f7SKerry Stevens free(arrmutex); 114551d315f7SKerry Stevens free(arrcond1); 114651d315f7SKerry Stevens free(arrcond2); 114751d315f7SKerry Stevens free(arrstart); 114851d315f7SKerry Stevens free(arrready); 114951d315f7SKerry Stevens free(job_main.pdata); 115051d315f7SKerry Stevens free(pVal); 115151d315f7SKerry Stevens } 115251d315f7SKerry Stevens else { 115351d315f7SKerry Stevens } 115451d315f7SKerry Stevens PetscFunctionReturn(0); 115551d315f7SKerry Stevens } 115651d315f7SKerry Stevens 115751d315f7SKerry Stevens #undef __FUNCT__ 115851d315f7SKerry Stevens #define __FUNCT__ "MainWait_Main" 115951d315f7SKerry Stevens void MainWait_Main() { 116051d315f7SKerry Stevens int i,ierr; 116151d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 116251d315f7SKerry Stevens ierr = pthread_mutex_lock(job_main.mutexarray[i]); 116351d315f7SKerry Stevens while(*(job_main.arrThreadReady[i])==PETSC_FALSE) { 116451d315f7SKerry Stevens ierr = pthread_cond_wait(job_main.cond1array[i],job_main.mutexarray[i]); 116551d315f7SKerry Stevens } 116651d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_main.mutexarray[i]); 116751d315f7SKerry Stevens } 116851d315f7SKerry Stevens } 116951d315f7SKerry Stevens 117051d315f7SKerry Stevens #undef __FUNCT__ 117151d315f7SKerry Stevens #define __FUNCT__ "MainJob_Main" 117251d315f7SKerry Stevens PetscErrorCode MainJob_Main(void* (*pFunc)(void*),void** data,PetscInt n) { 117351d315f7SKerry Stevens int i,ierr; 117451d315f7SKerry Stevens PetscErrorCode ijoberr = 0; 117551d315f7SKerry Stevens if(PetscUseThreadPool) { 117651d315f7SKerry Stevens MainWait(); //you know everyone is waiting to be signalled! 117751d315f7SKerry Stevens job_main.pfunc = pFunc; 117851d315f7SKerry Stevens job_main.pdata = data; 117951d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 118051d315f7SKerry Stevens *(job_main.arrThreadReady[i]) = PETSC_FALSE; //why do this? suppose you get into MainWait first 118151d315f7SKerry Stevens } 118251d315f7SKerry Stevens //tell the threads to go to work 118351d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 118451d315f7SKerry Stevens ierr = pthread_cond_signal(job_main.cond2array[i]); 118551d315f7SKerry Stevens } 118651d315f7SKerry Stevens if(pFunc!=FuncFinish) { 118751d315f7SKerry Stevens MainWait(); //why wait after? guarantees that job gets done before proceeding with result collection (if any) 118851d315f7SKerry Stevens } 118951d315f7SKerry Stevens } 119051d315f7SKerry Stevens else { 119151d315f7SKerry Stevens pthread_t* apThread = (pthread_t*)malloc(n*sizeof(pthread_t)); 119251d315f7SKerry Stevens PetscThreadRun(MPI_COMM_WORLD,pFunc,n,apThread,data); 119351d315f7SKerry Stevens PetscThreadStop(MPI_COMM_WORLD,n,apThread); //ensures that all threads are finished with the job 119451d315f7SKerry Stevens free(apThread); 119551d315f7SKerry Stevens } 119651d315f7SKerry Stevens if(ithreaderr) { 119751d315f7SKerry Stevens ijoberr = ithreaderr; 119851d315f7SKerry Stevens } 119951d315f7SKerry Stevens return ijoberr; 120051d315f7SKerry Stevens } 120151d315f7SKerry Stevens /**** ****/ 120251d315f7SKerry Stevens 120351d315f7SKerry Stevens /**** Chain Thread Functions ****/ 120451d315f7SKerry Stevens void* PetscThreadFunc_Chain(void* arg) { 120551d315f7SKerry Stevens PetscErrorCode iterr; 120651d315f7SKerry Stevens int icorr,ierr; 120751d315f7SKerry Stevens int* pId = (int*)arg; 120851d315f7SKerry Stevens int ThreadId = *pId; 120951d315f7SKerry Stevens int SubWorker = ThreadId + 1; 121051d315f7SKerry Stevens PetscBool PeeOn; 121151d315f7SKerry Stevens cpu_set_t mset; 1212*9e800a48SKerry Stevens //printf("Thread %d In Chain Thread Function\n",ThreadId); 121351d315f7SKerry Stevens icorr = ThreadCoreAffinity[ThreadId]; 121451d315f7SKerry Stevens CPU_ZERO(&mset); 121551d315f7SKerry Stevens CPU_SET(icorr,&mset); 121651d315f7SKerry Stevens sched_setaffinity(0,sizeof(cpu_set_t),&mset); 121751d315f7SKerry Stevens 121851d315f7SKerry Stevens if(ThreadId==(PetscMaxThreads-1)) { 121951d315f7SKerry Stevens PeeOn = PETSC_TRUE; 122051d315f7SKerry Stevens } 122151d315f7SKerry Stevens else { 122251d315f7SKerry Stevens PeeOn = PETSC_FALSE; 122351d315f7SKerry Stevens } 122451d315f7SKerry Stevens if(PeeOn==PETSC_FALSE) { 122551d315f7SKerry Stevens //check your subordinate, wait for him to be ready 122651d315f7SKerry Stevens ierr = pthread_mutex_lock(job_chain.mutexarray[SubWorker]); 122751d315f7SKerry Stevens while(*(job_chain.arrThreadReady[SubWorker])==PETSC_FALSE) { 122851d315f7SKerry Stevens //upon entry, automically releases the lock and blocks 122951d315f7SKerry Stevens //upon return, has the lock 123051d315f7SKerry Stevens ierr = pthread_cond_wait(job_chain.cond1array[SubWorker],job_chain.mutexarray[SubWorker]); 123151d315f7SKerry Stevens } 123251d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_chain.mutexarray[SubWorker]); 123351d315f7SKerry Stevens //your subordinate is now ready 123451d315f7SKerry Stevens } 123551d315f7SKerry Stevens ierr = pthread_mutex_lock(job_chain.mutexarray[ThreadId]); 123651d315f7SKerry Stevens //update your ready status 123751d315f7SKerry Stevens *(job_chain.arrThreadReady[ThreadId]) = PETSC_TRUE; 123851d315f7SKerry Stevens if(ThreadId==0) { 123951d315f7SKerry Stevens job_chain.eJobStat = JobCompleted; 124051d315f7SKerry Stevens //signal main 124151d315f7SKerry Stevens ierr = pthread_cond_signal(&main_cond); 124251d315f7SKerry Stevens } 124351d315f7SKerry Stevens else { 124451d315f7SKerry Stevens //tell your boss that you're ready to work 124551d315f7SKerry Stevens ierr = pthread_cond_signal(job_chain.cond1array[ThreadId]); 124651d315f7SKerry Stevens } 124751d315f7SKerry Stevens //the while loop needs to have an exit 124851d315f7SKerry Stevens //the 'main' thread can terminate all the threads by performing a broadcast 124951d315f7SKerry Stevens //and calling FuncFinish 125051d315f7SKerry Stevens while(PetscThreadGo) { 125151d315f7SKerry Stevens //need to check the condition to ensure we don't have to wait 125251d315f7SKerry Stevens //waiting when you don't have to causes problems 125351d315f7SKerry Stevens //also need to check the condition to ensure proper handling of spurious wakeups 125451d315f7SKerry Stevens while(*(job_chain.arrThreadReady[ThreadId])==PETSC_TRUE) { 125551d315f7SKerry Stevens //upon entry, automically releases the lock and blocks 125651d315f7SKerry Stevens //upon return, has the lock 125751d315f7SKerry Stevens ierr = pthread_cond_wait(job_chain.cond2array[ThreadId],job_chain.mutexarray[ThreadId]); 125851d315f7SKerry Stevens *(job_chain.arrThreadStarted[ThreadId]) = PETSC_TRUE; 125951d315f7SKerry Stevens *(job_chain.arrThreadReady[ThreadId]) = PETSC_FALSE; 126051d315f7SKerry Stevens } 126151d315f7SKerry Stevens if(ThreadId==0) { 126251d315f7SKerry Stevens job_chain.startJob = PETSC_FALSE; 126351d315f7SKerry Stevens job_chain.eJobStat = ThreadsWorking; 126451d315f7SKerry Stevens } 126551d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_chain.mutexarray[ThreadId]); 126651d315f7SKerry Stevens if(PeeOn==PETSC_FALSE) { 126751d315f7SKerry Stevens //tell your subworker it's time to get to work 126851d315f7SKerry Stevens ierr = pthread_cond_signal(job_chain.cond2array[SubWorker]); 126951d315f7SKerry Stevens } 127051d315f7SKerry Stevens //do your job 127151d315f7SKerry Stevens if(job_chain.pdata==NULL) { 127251d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_chain.pfunc(job_chain.pdata); 127351d315f7SKerry Stevens } 127451d315f7SKerry Stevens else { 127551d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_chain.pfunc(job_chain.pdata[ThreadId]); 127651d315f7SKerry Stevens } 127751d315f7SKerry Stevens if(iterr!=0) { 127851d315f7SKerry Stevens ithreaderr = 1; 127951d315f7SKerry Stevens } 128051d315f7SKerry Stevens if(PetscThreadGo) { 128151d315f7SKerry Stevens //reset job, get ready for more 128251d315f7SKerry Stevens if(PeeOn==PETSC_FALSE) { 128351d315f7SKerry Stevens //check your subordinate, wait for him to be ready 128451d315f7SKerry Stevens //how do you know for a fact that your subordinate has actually started? 128551d315f7SKerry Stevens ierr = pthread_mutex_lock(job_chain.mutexarray[SubWorker]); 128651d315f7SKerry Stevens while(*(job_chain.arrThreadReady[SubWorker])==PETSC_FALSE||*(job_chain.arrThreadStarted[SubWorker])==PETSC_FALSE) { 128751d315f7SKerry Stevens //upon entry, automically releases the lock and blocks 128851d315f7SKerry Stevens //upon return, has the lock 128951d315f7SKerry Stevens ierr = pthread_cond_wait(job_chain.cond1array[SubWorker],job_chain.mutexarray[SubWorker]); 129051d315f7SKerry Stevens } 129151d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_chain.mutexarray[SubWorker]); 129251d315f7SKerry Stevens //your subordinate is now ready 129351d315f7SKerry Stevens } 129451d315f7SKerry Stevens ierr = pthread_mutex_lock(job_chain.mutexarray[ThreadId]); 129551d315f7SKerry Stevens *(job_chain.arrThreadReady[ThreadId]) = PETSC_TRUE; 129651d315f7SKerry Stevens if(ThreadId==0) { 129751d315f7SKerry Stevens job_chain.eJobStat = JobCompleted; //foreman: last thread to complete, guaranteed! 129851d315f7SKerry Stevens //root thread (foreman) signals 'main' 129951d315f7SKerry Stevens ierr = pthread_cond_signal(&main_cond); 130051d315f7SKerry Stevens } 130151d315f7SKerry Stevens else { 130251d315f7SKerry Stevens //signal your boss before you go to sleep 130351d315f7SKerry Stevens ierr = pthread_cond_signal(job_chain.cond1array[ThreadId]); 130451d315f7SKerry Stevens } 130551d315f7SKerry Stevens } 130651d315f7SKerry Stevens } 130751d315f7SKerry Stevens return NULL; 130851d315f7SKerry Stevens } 130951d315f7SKerry Stevens 131051d315f7SKerry Stevens #undef __FUNCT__ 131151d315f7SKerry Stevens #define __FUNCT__ "PetscThreadInitialize_Chain" 131251d315f7SKerry Stevens void* PetscThreadInitialize_Chain(PetscInt N) { 131351d315f7SKerry Stevens PetscInt i,ierr; 131451d315f7SKerry Stevens int status; 131551d315f7SKerry Stevens 131651d315f7SKerry Stevens if(PetscUseThreadPool) { 131751d315f7SKerry Stevens size_t Val1 = (size_t)CACHE_LINE_SIZE; 131851d315f7SKerry Stevens size_t Val2 = (size_t)PetscMaxThreads*CACHE_LINE_SIZE; 131951d315f7SKerry Stevens arrmutex = (char*)memalign(Val1,Val2); 132051d315f7SKerry Stevens arrcond1 = (char*)memalign(Val1,Val2); 132151d315f7SKerry Stevens arrcond2 = (char*)memalign(Val1,Val2); 132251d315f7SKerry Stevens arrstart = (char*)memalign(Val1,Val2); 132351d315f7SKerry Stevens arrready = (char*)memalign(Val1,Val2); 132451d315f7SKerry Stevens job_chain.mutexarray = (pthread_mutex_t**)malloc(PetscMaxThreads*sizeof(pthread_mutex_t*)); 132551d315f7SKerry Stevens job_chain.cond1array = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*)); 132651d315f7SKerry Stevens job_chain.cond2array = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*)); 132751d315f7SKerry Stevens job_chain.arrThreadStarted = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*)); 132851d315f7SKerry Stevens job_chain.arrThreadReady = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*)); 132951d315f7SKerry Stevens //initialize job structure 133051d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 133151d315f7SKerry Stevens job_chain.mutexarray[i] = (pthread_mutex_t*)(arrmutex+CACHE_LINE_SIZE*i); 133251d315f7SKerry Stevens job_chain.cond1array[i] = (pthread_cond_t*)(arrcond1+CACHE_LINE_SIZE*i); 133351d315f7SKerry Stevens job_chain.cond2array[i] = (pthread_cond_t*)(arrcond2+CACHE_LINE_SIZE*i); 133451d315f7SKerry Stevens job_chain.arrThreadStarted[i] = (PetscBool*)(arrstart+CACHE_LINE_SIZE*i); 133551d315f7SKerry Stevens job_chain.arrThreadReady[i] = (PetscBool*)(arrready+CACHE_LINE_SIZE*i); 133651d315f7SKerry Stevens } 133751d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 133851d315f7SKerry Stevens ierr = pthread_mutex_init(job_chain.mutexarray[i],NULL); 133951d315f7SKerry Stevens ierr = pthread_cond_init(job_chain.cond1array[i],NULL); 134051d315f7SKerry Stevens ierr = pthread_cond_init(job_chain.cond2array[i],NULL); 134151d315f7SKerry Stevens *(job_chain.arrThreadStarted[i]) = PETSC_FALSE; 134251d315f7SKerry Stevens *(job_chain.arrThreadReady[i]) = PETSC_FALSE; 134351d315f7SKerry Stevens } 134451d315f7SKerry Stevens job_chain.pfunc = NULL; 134551d315f7SKerry Stevens job_chain.pdata = (void**)malloc(N*sizeof(void*)); 134651d315f7SKerry Stevens job_chain.startJob = PETSC_FALSE; 134751d315f7SKerry Stevens job_chain.eJobStat = JobInitiated; 134851d315f7SKerry Stevens pVal = (int*)malloc(N*sizeof(int)); 134951d315f7SKerry Stevens //allocate memory in the heap for the thread structure 135051d315f7SKerry Stevens PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t)); 135151d315f7SKerry Stevens //create threads 135251d315f7SKerry Stevens for(i=0; i<N; i++) { 135351d315f7SKerry Stevens pVal[i] = i; 135451d315f7SKerry Stevens status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]); 135551d315f7SKerry Stevens //error check 135651d315f7SKerry Stevens } 135751d315f7SKerry Stevens } 135851d315f7SKerry Stevens else { 135951d315f7SKerry Stevens } 136051d315f7SKerry Stevens return NULL; 136151d315f7SKerry Stevens } 136251d315f7SKerry Stevens 136351d315f7SKerry Stevens 136451d315f7SKerry Stevens #undef __FUNCT__ 136551d315f7SKerry Stevens #define __FUNCT__ "PetscThreadFinalize_Chain" 136651d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Chain() { 136751d315f7SKerry Stevens int i,ierr; 136851d315f7SKerry Stevens void* jstatus; 136951d315f7SKerry Stevens 137051d315f7SKerry Stevens PetscFunctionBegin; 137151d315f7SKerry Stevens 137251d315f7SKerry Stevens if(PetscUseThreadPool) { 137351d315f7SKerry Stevens MainJob(FuncFinish,NULL,PetscMaxThreads); //set up job and broadcast work 137451d315f7SKerry Stevens //join the threads 137551d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 137651d315f7SKerry Stevens ierr = pthread_join(PetscThreadPoint[i],&jstatus); 137751d315f7SKerry Stevens //do error checking 137851d315f7SKerry Stevens } 137951d315f7SKerry Stevens free(PetscThreadPoint); 138051d315f7SKerry Stevens free(arrmutex); 138151d315f7SKerry Stevens free(arrcond1); 138251d315f7SKerry Stevens free(arrcond2); 138351d315f7SKerry Stevens free(arrstart); 138451d315f7SKerry Stevens free(arrready); 138551d315f7SKerry Stevens free(job_chain.pdata); 138651d315f7SKerry Stevens free(pVal); 138751d315f7SKerry Stevens } 138851d315f7SKerry Stevens else { 138951d315f7SKerry Stevens } 139051d315f7SKerry Stevens PetscFunctionReturn(0); 139151d315f7SKerry Stevens } 139251d315f7SKerry Stevens 139351d315f7SKerry Stevens #undef __FUNCT__ 139451d315f7SKerry Stevens #define __FUNCT__ "MainWait_Chain" 139551d315f7SKerry Stevens void MainWait_Chain() { 139651d315f7SKerry Stevens int ierr; 139751d315f7SKerry Stevens ierr = pthread_mutex_lock(job_chain.mutexarray[0]); 139851d315f7SKerry Stevens while(job_chain.eJobStat<JobCompleted||job_chain.startJob==PETSC_TRUE) { 139951d315f7SKerry Stevens ierr = pthread_cond_wait(&main_cond,job_chain.mutexarray[0]); 140051d315f7SKerry Stevens } 140151d315f7SKerry Stevens ierr = pthread_mutex_unlock(job_chain.mutexarray[0]); 140251d315f7SKerry Stevens } 140351d315f7SKerry Stevens 140451d315f7SKerry Stevens #undef __FUNCT__ 140551d315f7SKerry Stevens #define __FUNCT__ "MainJob_Chain" 140651d315f7SKerry Stevens PetscErrorCode MainJob_Chain(void* (*pFunc)(void*),void** data,PetscInt n) { 140751d315f7SKerry Stevens int i,ierr; 140851d315f7SKerry Stevens PetscErrorCode ijoberr = 0; 140951d315f7SKerry Stevens if(PetscUseThreadPool) { 141051d315f7SKerry Stevens MainWait(); 141151d315f7SKerry Stevens job_chain.pfunc = pFunc; 141251d315f7SKerry Stevens job_chain.pdata = data; 141351d315f7SKerry Stevens job_chain.startJob = PETSC_TRUE; 141451d315f7SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 141551d315f7SKerry Stevens *(job_chain.arrThreadStarted[i]) = PETSC_FALSE; 141651d315f7SKerry Stevens } 141751d315f7SKerry Stevens job_chain.eJobStat = JobInitiated; 141851d315f7SKerry Stevens ierr = pthread_cond_signal(job_chain.cond2array[0]); 141951d315f7SKerry Stevens if(pFunc!=FuncFinish) { 142051d315f7SKerry Stevens MainWait(); //why wait after? guarantees that job gets done before proceeding with result collection (if any) 142151d315f7SKerry Stevens } 142251d315f7SKerry Stevens } 142351d315f7SKerry Stevens else { 142451d315f7SKerry Stevens pthread_t* apThread = (pthread_t*)malloc(n*sizeof(pthread_t)); 142551d315f7SKerry Stevens PetscThreadRun(MPI_COMM_WORLD,pFunc,n,apThread,data); 142651d315f7SKerry Stevens PetscThreadStop(MPI_COMM_WORLD,n,apThread); //ensures that all threads are finished with the job 142751d315f7SKerry Stevens free(apThread); 142851d315f7SKerry Stevens } 142951d315f7SKerry Stevens if(ithreaderr) { 143051d315f7SKerry Stevens ijoberr = ithreaderr; 143151d315f7SKerry Stevens } 143251d315f7SKerry Stevens return ijoberr; 143351d315f7SKerry Stevens } 143451d315f7SKerry Stevens /**** ****/ 143551d315f7SKerry Stevens 143651d315f7SKerry Stevens /**** True Thread Functions ****/ 143751d315f7SKerry Stevens void* PetscThreadFunc_True(void* arg) { 143851d315f7SKerry Stevens int icorr,ierr,iVal; 143951dcc849SKerry Stevens int* pId = (int*)arg; 144051dcc849SKerry Stevens int ThreadId = *pId; 14410ca81413SKerry Stevens PetscErrorCode iterr; 144251d315f7SKerry Stevens cpu_set_t mset; 1443*9e800a48SKerry Stevens //printf("Thread %d In True Pool Thread Function\n",ThreadId); 144451d315f7SKerry Stevens icorr = ThreadCoreAffinity[ThreadId]; 144551d315f7SKerry Stevens CPU_ZERO(&mset); 144651d315f7SKerry Stevens CPU_SET(icorr,&mset); 144751d315f7SKerry Stevens sched_setaffinity(0,sizeof(cpu_set_t),&mset); 144851d315f7SKerry Stevens 144951d315f7SKerry Stevens ierr = pthread_mutex_lock(&job_true.mutex); 145051d315f7SKerry Stevens job_true.iNumReadyThreads++; 145151d315f7SKerry Stevens if(job_true.iNumReadyThreads==PetscMaxThreads) { 145251dcc849SKerry Stevens ierr = pthread_cond_signal(&main_cond); 145351dcc849SKerry Stevens } 145451dcc849SKerry Stevens //the while loop needs to have an exit 145551d315f7SKerry Stevens //the 'main' thread can terminate all the threads by performing a broadcast 145651dcc849SKerry Stevens //and calling FuncFinish 145751dcc849SKerry Stevens while(PetscThreadGo) { 145851dcc849SKerry Stevens //need to check the condition to ensure we don't have to wait 145951dcc849SKerry Stevens //waiting when you don't have to causes problems 146051dcc849SKerry Stevens //also need to wait if another thread sneaks in and messes with the predicate 146151d315f7SKerry Stevens while(job_true.startJob==PETSC_FALSE&&job_true.iNumJobThreads==0) { 146251dcc849SKerry Stevens //upon entry, automically releases the lock and blocks 146351dcc849SKerry Stevens //upon return, has the lock 146451d315f7SKerry Stevens ierr = pthread_cond_wait(&job_true.cond,&job_true.mutex); 146551dcc849SKerry Stevens } 146651d315f7SKerry Stevens job_true.startJob = PETSC_FALSE; 146751d315f7SKerry Stevens job_true.iNumJobThreads--; 146851d315f7SKerry Stevens job_true.iNumReadyThreads--; 146951d315f7SKerry Stevens iVal = PetscMaxThreads-job_true.iNumReadyThreads-1; 147051d315f7SKerry Stevens pthread_mutex_unlock(&job_true.mutex); 147151d315f7SKerry Stevens if(job_true.pdata==NULL) { 147251d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_true.pfunc(job_true.pdata); 147351dcc849SKerry Stevens } 147451dcc849SKerry Stevens else { 147551d315f7SKerry Stevens iterr = (PetscErrorCode)(long int)job_true.pfunc(job_true.pdata[iVal]); 147651dcc849SKerry Stevens } 14770ca81413SKerry Stevens if(iterr!=0) { 14780ca81413SKerry Stevens ithreaderr = 1; 14790ca81413SKerry Stevens } 148051d315f7SKerry Stevens //the barrier is necessary BECAUSE: look at job_true.iNumReadyThreads 14810ca81413SKerry Stevens //what happens if a thread finishes before they all start? BAD! 14820ca81413SKerry Stevens //what happens if a thread finishes before any else start? BAD! 148351d315f7SKerry Stevens pthread_barrier_wait(job_true.pbarr); //ensures all threads are finished 148451dcc849SKerry Stevens //reset job 148551dcc849SKerry Stevens if(PetscThreadGo) { 148651d315f7SKerry Stevens pthread_mutex_lock(&job_true.mutex); 148751d315f7SKerry Stevens job_true.iNumReadyThreads++; 148851d315f7SKerry Stevens if(job_true.iNumReadyThreads==PetscMaxThreads) { 14890ca81413SKerry Stevens //signal the 'main' thread that the job is done! (only done once) 149051dcc849SKerry Stevens ierr = pthread_cond_signal(&main_cond); 149151dcc849SKerry Stevens } 149251dcc849SKerry Stevens } 149351dcc849SKerry Stevens } 149451dcc849SKerry Stevens return NULL; 149551dcc849SKerry Stevens } 149651dcc849SKerry Stevens 1497f09cb4aaSKerry Stevens #undef __FUNCT__ 149851d315f7SKerry Stevens #define __FUNCT__ "PetscThreadInitialize_True" 149951d315f7SKerry Stevens void* PetscThreadInitialize_True(PetscInt N) { 150051dcc849SKerry Stevens PetscInt i; 150151dcc849SKerry Stevens int status; 15020ca81413SKerry Stevens 15030ca81413SKerry Stevens if(PetscUseThreadPool) { 1504f09cb4aaSKerry Stevens pVal = (int*)malloc(N*sizeof(int)); 150551dcc849SKerry Stevens //allocate memory in the heap for the thread structure 150651dcc849SKerry Stevens PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t)); 150751dcc849SKerry Stevens BarrPoint = (pthread_barrier_t*)malloc((N+1)*sizeof(pthread_barrier_t)); //BarrPoint[0] makes no sense, don't use it! 150851d315f7SKerry Stevens job_true.pdata = (void**)malloc(N*sizeof(void*)); 150951dcc849SKerry Stevens for(i=0; i<N; i++) { 1510f09cb4aaSKerry Stevens pVal[i] = i; 1511f09cb4aaSKerry Stevens status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]); 151251dcc849SKerry Stevens //error check to ensure proper thread creation 151351dcc849SKerry Stevens status = pthread_barrier_init(&BarrPoint[i+1],NULL,i+1); 151451dcc849SKerry Stevens //error check 151551dcc849SKerry Stevens } 15160ca81413SKerry Stevens } 15170ca81413SKerry Stevens else { 15180ca81413SKerry Stevens } 151951dcc849SKerry Stevens return NULL; 152051dcc849SKerry Stevens } 152151dcc849SKerry Stevens 1522f09cb4aaSKerry Stevens 1523f09cb4aaSKerry Stevens #undef __FUNCT__ 152451d315f7SKerry Stevens #define __FUNCT__ "PetscThreadFinalize_True" 152551d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_True() { 152651dcc849SKerry Stevens int i,ierr; 152751dcc849SKerry Stevens void* jstatus; 152851dcc849SKerry Stevens 152951dcc849SKerry Stevens PetscFunctionBegin; 15300ca81413SKerry Stevens 15310ca81413SKerry Stevens if(PetscUseThreadPool) { 15320ca81413SKerry Stevens MainJob(FuncFinish,NULL,PetscMaxThreads); //set up job and broadcast work 153351dcc849SKerry Stevens //join the threads 153451dcc849SKerry Stevens for(i=0; i<PetscMaxThreads; i++) { 153551dcc849SKerry Stevens ierr = pthread_join(PetscThreadPoint[i],&jstatus); 153651dcc849SKerry Stevens //do error checking 153751dcc849SKerry Stevens } 153851dcc849SKerry Stevens free(BarrPoint); 153951dcc849SKerry Stevens free(PetscThreadPoint); 15400ca81413SKerry Stevens } 15410ca81413SKerry Stevens else { 15420ca81413SKerry Stevens } 154351dcc849SKerry Stevens PetscFunctionReturn(0); 154451dcc849SKerry Stevens } 154551dcc849SKerry Stevens 1546f09cb4aaSKerry Stevens #undef __FUNCT__ 154751d315f7SKerry Stevens #define __FUNCT__ "MainWait_True" 154851d315f7SKerry Stevens void MainWait_True() { 154951dcc849SKerry Stevens int ierr; 155051d315f7SKerry Stevens while(job_true.iNumReadyThreads<PetscMaxThreads||job_true.startJob==PETSC_TRUE) { 155151d315f7SKerry Stevens ierr = pthread_cond_wait(&main_cond,&job_true.mutex); 155251dcc849SKerry Stevens } 155351d315f7SKerry Stevens ierr = pthread_mutex_unlock(&job_true.mutex); 155451dcc849SKerry Stevens } 155551dcc849SKerry Stevens 1556f09cb4aaSKerry Stevens #undef __FUNCT__ 155751d315f7SKerry Stevens #define __FUNCT__ "MainJob_True" 155851d315f7SKerry Stevens PetscErrorCode MainJob_True(void* (*pFunc)(void*),void** data,PetscInt n) { 155951dcc849SKerry Stevens int ierr; 15600ca81413SKerry Stevens PetscErrorCode ijoberr = 0; 15610ca81413SKerry Stevens if(PetscUseThreadPool) { 15620ca81413SKerry Stevens MainWait(); 156351d315f7SKerry Stevens job_true.pfunc = pFunc; 156451d315f7SKerry Stevens job_true.pdata = data; 156551d315f7SKerry Stevens job_true.pbarr = &BarrPoint[n]; 156651d315f7SKerry Stevens job_true.iNumJobThreads = n; 156751d315f7SKerry Stevens job_true.startJob = PETSC_TRUE; 156851d315f7SKerry Stevens ierr = pthread_cond_broadcast(&job_true.cond); 15690ca81413SKerry Stevens if(pFunc!=FuncFinish) { 15700ca81413SKerry Stevens MainWait(); //why wait after? guarantees that job gets done 15710ca81413SKerry Stevens } 15720ca81413SKerry Stevens } 15730ca81413SKerry Stevens else { 15740ca81413SKerry Stevens pthread_t* apThread = (pthread_t*)malloc(n*sizeof(pthread_t)); 15750ca81413SKerry Stevens PetscThreadRun(MPI_COMM_WORLD,pFunc,n,apThread,data); 15760ca81413SKerry Stevens PetscThreadStop(MPI_COMM_WORLD,n,apThread); //ensures that all threads are finished with the job 15770ca81413SKerry Stevens free(apThread); 15780ca81413SKerry Stevens } 15790ca81413SKerry Stevens if(ithreaderr) { 15800ca81413SKerry Stevens ijoberr = ithreaderr; 15810ca81413SKerry Stevens } 15820ca81413SKerry Stevens return ijoberr; 158351dcc849SKerry Stevens } 158451d315f7SKerry Stevens /**** ****/ 158551dcc849SKerry Stevens 158651dcc849SKerry Stevens void* FuncFinish(void* arg) { 158751dcc849SKerry Stevens PetscThreadGo = PETSC_FALSE; 15880ca81413SKerry Stevens return(0); 158951dcc849SKerry Stevens } 1590