xref: /petsc/src/sys/objects/init.c (revision 9e800a489d4dd7df6e219efb49e6e50c80139b3f)
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