xref: /petsc/src/sys/objects/init.c (revision ba61063db8cd96e5a5f702c43a4ce6e281e3e2a6)
1e5c89e4eSSatish Balay /*
2e5c89e4eSSatish Balay 
3e5c89e4eSSatish Balay    This file defines part of the initialization of PETSc
4e5c89e4eSSatish Balay 
5e5c89e4eSSatish Balay   This file uses regular malloc and free because it cannot know
6e5c89e4eSSatish Balay   what malloc is being used until it has already processed the input.
7e5c89e4eSSatish Balay */
8e5c89e4eSSatish Balay 
951d315f7SKerry Stevens #define _GNU_SOURCE
1051d315f7SKerry Stevens #include <sched.h>
11c6db04a5SJed Brown #include <petscsys.h>        /*I  "petscsys.h"   I*/
12*ba61063dSBarry Smith #if defined(PETSC_USE_PTHREAD)
1351dcc849SKerry Stevens #include <pthread.h>
14*ba61063dSBarry Smith #endif
15*ba61063dSBarry Smith #if defined(PETSC_HAVE_SYS_SYSINFO_H)
1651d315f7SKerry Stevens #include <sys/sysinfo.h>
17*ba61063dSBarry Smith #endif
1851d315f7SKerry Stevens #include <unistd.h>
19e5c89e4eSSatish Balay #if defined(PETSC_HAVE_STDLIB_H)
20e5c89e4eSSatish Balay #include <stdlib.h>
21e5c89e4eSSatish Balay #endif
22e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H)
23e5c89e4eSSatish Balay #include <malloc.h>
24e5c89e4eSSatish Balay #endif
25555d055bSBarry Smith #if defined(PETSC_HAVE_VALGRIND)
26555d055bSBarry Smith #include <valgrind/valgrind.h>
27555d055bSBarry Smith #endif
28555d055bSBarry Smith 
29e5c89e4eSSatish Balay /* ------------------------Nasty global variables -------------------------------*/
30e5c89e4eSSatish Balay /*
31e5c89e4eSSatish Balay      Indicates if PETSc started up MPI, or it was
32e5c89e4eSSatish Balay    already started before PETSc was initialized.
33e5c89e4eSSatish Balay */
347087cfbeSBarry Smith PetscBool    PetscBeganMPI         = PETSC_FALSE;
357087cfbeSBarry Smith PetscBool    PetscInitializeCalled = PETSC_FALSE;
367087cfbeSBarry Smith PetscBool    PetscFinalizeCalled   = PETSC_FALSE;
3751dcc849SKerry Stevens PetscBool    PetscUseThreadPool    = PETSC_FALSE;
3851dcc849SKerry Stevens PetscBool    PetscThreadGo         = PETSC_TRUE;
397087cfbeSBarry Smith PetscMPIInt  PetscGlobalRank = -1;
407087cfbeSBarry Smith PetscMPIInt  PetscGlobalSize = -1;
41*ba61063dSBarry Smith 
42*ba61063dSBarry Smith #if defined(PETSC_USE_PTHREAD_CLASSES)
4351dcc849SKerry Stevens PetscMPIInt  PetscMaxThreads = 2;
4451dcc849SKerry Stevens pthread_t*   PetscThreadPoint;
45*ba61063dSBarry Smith #if defined(PETSC_HAVE_PTHREAD_BARRIER)
46*ba61063dSBarry Smith pthread_barrier_t* BarrPoint;   /* used by 'true' thread pool */
47*ba61063dSBarry Smith #endif
4851d315f7SKerry Stevens PetscErrorCode ithreaderr = 0;
49f09cb4aaSKerry Stevens int*         pVal;
5051dcc849SKerry Stevens 
51*ba61063dSBarry Smith #define CACHE_LINE_SIZE 64  /* used by 'chain', 'main','tree' thread pools */
5251d315f7SKerry Stevens int* ThreadCoreAffinity;
5351d315f7SKerry Stevens 
54*ba61063dSBarry Smith typedef enum {JobInitiated,ThreadsWorking,JobCompleted} estat;  /* used by 'chain','tree' thread pool */
5551d315f7SKerry Stevens 
5651d315f7SKerry Stevens typedef struct {
5751d315f7SKerry Stevens   pthread_mutex_t** mutexarray;
5851d315f7SKerry Stevens   pthread_cond_t**  cond1array;
5951d315f7SKerry Stevens   pthread_cond_t** cond2array;
6051d315f7SKerry Stevens   void* (*pfunc)(void*);
6151d315f7SKerry Stevens   void** pdata;
6251d315f7SKerry Stevens   PetscBool startJob;
6351d315f7SKerry Stevens   estat eJobStat;
6451d315f7SKerry Stevens   PetscBool** arrThreadStarted;
6551d315f7SKerry Stevens   PetscBool** arrThreadReady;
6651d315f7SKerry Stevens } sjob_tree;
6751d315f7SKerry Stevens sjob_tree job_tree;
6851d315f7SKerry Stevens typedef struct {
6951d315f7SKerry Stevens   pthread_mutex_t** mutexarray;
7051d315f7SKerry Stevens   pthread_cond_t**  cond1array;
7151d315f7SKerry Stevens   pthread_cond_t** cond2array;
7251d315f7SKerry Stevens   void* (*pfunc)(void*);
7351d315f7SKerry Stevens   void** pdata;
7451d315f7SKerry Stevens   PetscBool** arrThreadReady;
7551d315f7SKerry Stevens } sjob_main;
7651d315f7SKerry Stevens sjob_main job_main;
7751d315f7SKerry Stevens typedef struct {
7851d315f7SKerry Stevens   pthread_mutex_t** mutexarray;
7951d315f7SKerry Stevens   pthread_cond_t**  cond1array;
8051d315f7SKerry Stevens   pthread_cond_t** cond2array;
8151d315f7SKerry Stevens   void* (*pfunc)(void*);
8251d315f7SKerry Stevens   void** pdata;
8351d315f7SKerry Stevens   PetscBool startJob;
8451d315f7SKerry Stevens   estat eJobStat;
8551d315f7SKerry Stevens   PetscBool** arrThreadStarted;
8651d315f7SKerry Stevens   PetscBool** arrThreadReady;
8751d315f7SKerry Stevens } sjob_chain;
8851d315f7SKerry Stevens sjob_chain job_chain;
89*ba61063dSBarry Smith #if defined(PETSC_HAVE_PTHREAD_BARRIER)
9051dcc849SKerry Stevens typedef struct {
9151dcc849SKerry Stevens   pthread_mutex_t mutex;
9251dcc849SKerry Stevens   pthread_cond_t cond;
9351dcc849SKerry Stevens   void* (*pfunc)(void*);
9451dcc849SKerry Stevens   void** pdata;
9551dcc849SKerry Stevens   pthread_barrier_t* pbarr;
9651dcc849SKerry Stevens   int iNumJobThreads;
9751dcc849SKerry Stevens   int iNumReadyThreads;
9851dcc849SKerry Stevens   PetscBool startJob;
9951d315f7SKerry Stevens } sjob_true;
10051d315f7SKerry Stevens sjob_true job_true = {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER,NULL,NULL,NULL,0,0,PETSC_FALSE};
101*ba61063dSBarry Smith #endif
10251dcc849SKerry Stevens 
103*ba61063dSBarry Smith pthread_cond_t  main_cond  = PTHREAD_COND_INITIALIZER;  /* used by 'true', 'chain','tree' thread pools */
104*ba61063dSBarry Smith char* arrmutex; /* used by 'chain','main','tree' thread pools */
105*ba61063dSBarry Smith char* arrcond1; /* used by 'chain','main','tree' thread pools */
106*ba61063dSBarry Smith char* arrcond2; /* used by 'chain','main','tree' thread pools */
107*ba61063dSBarry Smith char* arrstart; /* used by 'chain','main','tree' thread pools */
108*ba61063dSBarry Smith char* arrready; /* used by 'chain','main','tree' thread pools */
10951dcc849SKerry Stevens 
11051d315f7SKerry Stevens /* Function Pointers */
11151d315f7SKerry Stevens void*          (*PetscThreadFunc)(void*) = NULL;
11251d315f7SKerry Stevens void*          (*PetscThreadInitialize)(PetscInt) = NULL;
11351d315f7SKerry Stevens PetscErrorCode (*PetscThreadFinalize)(void) = NULL;
11451d315f7SKerry Stevens void           (*MainWait)(void) = NULL;
11551d315f7SKerry Stevens PetscErrorCode (*MainJob)(void* (*pFunc)(void*),void**,PetscInt) = NULL;
11651d315f7SKerry Stevens /**** Tree Functions ****/
11751d315f7SKerry Stevens void*          PetscThreadFunc_Tree(void*);
11851d315f7SKerry Stevens void*          PetscThreadInitialize_Tree(PetscInt);
11951d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Tree(void);
12051d315f7SKerry Stevens void           MainWait_Tree(void);
12151d315f7SKerry Stevens PetscErrorCode MainJob_Tree(void* (*pFunc)(void*),void**,PetscInt);
12251d315f7SKerry Stevens /**** Main Functions ****/
12351d315f7SKerry Stevens void*          PetscThreadFunc_Main(void*);
12451d315f7SKerry Stevens void*          PetscThreadInitialize_Main(PetscInt);
12551d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Main(void);
12651d315f7SKerry Stevens void           MainWait_Main(void);
12751d315f7SKerry Stevens PetscErrorCode MainJob_Main(void* (*pFunc)(void*),void**,PetscInt);
12851d315f7SKerry Stevens /**** Chain Functions ****/
12951d315f7SKerry Stevens void*          PetscThreadFunc_Chain(void*);
13051d315f7SKerry Stevens void*          PetscThreadInitialize_Chain(PetscInt);
13151d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Chain(void);
13251d315f7SKerry Stevens void           MainWait_Chain(void);
13351d315f7SKerry Stevens PetscErrorCode MainJob_Chain(void* (*pFunc)(void*),void**,PetscInt);
13451d315f7SKerry Stevens /**** True Functions ****/
13551d315f7SKerry Stevens void*          PetscThreadFunc_True(void*);
13651d315f7SKerry Stevens void*          PetscThreadInitialize_True(PetscInt);
13751d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_True(void);
13851d315f7SKerry Stevens void           MainWait_True(void);
13951d315f7SKerry Stevens PetscErrorCode MainJob_True(void* (*pFunc)(void*),void**,PetscInt);
14051d315f7SKerry Stevens /****  ****/
14151d315f7SKerry Stevens 
14251dcc849SKerry Stevens void* FuncFinish(void*);
1430ca81413SKerry Stevens void* PetscThreadRun(MPI_Comm Comm,void* (*pFunc)(void*),int,pthread_t*,void**);
1440ca81413SKerry Stevens void* PetscThreadStop(MPI_Comm Comm,int,pthread_t*);
145*ba61063dSBarry Smith #endif
146e5c89e4eSSatish Balay 
147e5c89e4eSSatish Balay #if defined(PETSC_USE_COMPLEX)
148e5c89e4eSSatish Balay #if defined(PETSC_COMPLEX_INSTANTIATE)
149e5c89e4eSSatish Balay template <> class std::complex<double>; /* instantiate complex template class */
150e5c89e4eSSatish Balay #endif
1512c876bd9SBarry Smith #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
1527087cfbeSBarry Smith MPI_Datatype   MPI_C_DOUBLE_COMPLEX;
1537087cfbeSBarry Smith MPI_Datatype   MPI_C_COMPLEX;
1542c876bd9SBarry Smith #endif
1557087cfbeSBarry Smith PetscScalar    PETSC_i;
156e5c89e4eSSatish Balay #else
1577087cfbeSBarry Smith PetscScalar    PETSC_i = 0.0;
158e5c89e4eSSatish Balay #endif
159ce63c4c1SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
160c90a1750SBarry Smith MPI_Datatype   MPIU___FLOAT128 = 0;
161c90a1750SBarry Smith #endif
1627087cfbeSBarry Smith MPI_Datatype   MPIU_2SCALAR = 0;
1637087cfbeSBarry Smith MPI_Datatype   MPIU_2INT = 0;
16475567043SBarry Smith 
165e5c89e4eSSatish Balay /*
166e5c89e4eSSatish Balay      These are needed by petscbt.h
167e5c89e4eSSatish Balay */
168c6db04a5SJed Brown #include <petscbt.h>
1697087cfbeSBarry Smith char      _BT_mask = ' ';
1707087cfbeSBarry Smith char      _BT_c = ' ';
1717087cfbeSBarry Smith PetscInt  _BT_idx  = 0;
172e5c89e4eSSatish Balay 
173e5c89e4eSSatish Balay /*
174e5c89e4eSSatish Balay        Function that is called to display all error messages
175e5c89e4eSSatish Balay */
1767087cfbeSBarry Smith PetscErrorCode  (*PetscErrorPrintf)(const char [],...)          = PetscErrorPrintfDefault;
1777087cfbeSBarry Smith PetscErrorCode  (*PetscHelpPrintf)(MPI_Comm,const char [],...)  = PetscHelpPrintfDefault;
178238ccf28SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE)
1797087cfbeSBarry Smith PetscErrorCode  (*PetscVFPrintf)(FILE*,const char[],va_list)    = PetscVFPrintf_Matlab;
180238ccf28SShri Abhyankar #else
1817087cfbeSBarry Smith PetscErrorCode  (*PetscVFPrintf)(FILE*,const char[],va_list)    = PetscVFPrintfDefault;
182238ccf28SShri Abhyankar #endif
183bab1f7e6SVictor Minden /*
1848154be41SBarry Smith   This is needed to turn on/off cusp synchronization */
1858154be41SBarry Smith PetscBool   synchronizeCUSP = PETSC_FALSE;
186bab1f7e6SVictor Minden 
187e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/
188e5c89e4eSSatish Balay /*
189e5c89e4eSSatish Balay    Optional file where all PETSc output from various prints is saved
190e5c89e4eSSatish Balay */
191e5c89e4eSSatish Balay FILE *petsc_history = PETSC_NULL;
192e5c89e4eSSatish Balay 
193e5c89e4eSSatish Balay #undef __FUNCT__
194f3dea69dSBarry Smith #define __FUNCT__ "PetscOpenHistoryFile"
1957087cfbeSBarry Smith PetscErrorCode  PetscOpenHistoryFile(const char filename[],FILE **fd)
196e5c89e4eSSatish Balay {
197e5c89e4eSSatish Balay   PetscErrorCode ierr;
198e5c89e4eSSatish Balay   PetscMPIInt    rank,size;
199e5c89e4eSSatish Balay   char           pfile[PETSC_MAX_PATH_LEN],pname[PETSC_MAX_PATH_LEN],fname[PETSC_MAX_PATH_LEN],date[64];
200e5c89e4eSSatish Balay   char           version[256];
201e5c89e4eSSatish Balay 
202e5c89e4eSSatish Balay   PetscFunctionBegin;
203e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
204e5c89e4eSSatish Balay   if (!rank) {
205e5c89e4eSSatish Balay     char        arch[10];
206f56c2debSBarry Smith     int         err;
20788c29154SBarry Smith     PetscViewer viewer;
208f56c2debSBarry Smith 
209e5c89e4eSSatish Balay     ierr = PetscGetArchType(arch,10);CHKERRQ(ierr);
210e5c89e4eSSatish Balay     ierr = PetscGetDate(date,64);CHKERRQ(ierr);
211a523d312SBarry Smith     ierr = PetscGetVersion(version,256);CHKERRQ(ierr);
212e5c89e4eSSatish Balay     ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
213e5c89e4eSSatish Balay     if (filename) {
214e5c89e4eSSatish Balay       ierr = PetscFixFilename(filename,fname);CHKERRQ(ierr);
215e5c89e4eSSatish Balay     } else {
216e5c89e4eSSatish Balay       ierr = PetscGetHomeDirectory(pfile,240);CHKERRQ(ierr);
217e5c89e4eSSatish Balay       ierr = PetscStrcat(pfile,"/.petschistory");CHKERRQ(ierr);
218e5c89e4eSSatish Balay       ierr = PetscFixFilename(pfile,fname);CHKERRQ(ierr);
219e5c89e4eSSatish Balay     }
220e5c89e4eSSatish Balay 
221e32f2f54SBarry Smith     *fd = fopen(fname,"a"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file: %s",fname);
222e5c89e4eSSatish Balay     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr);
223e5c89e4eSSatish Balay     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"%s %s\n",version,date);CHKERRQ(ierr);
224e5c89e4eSSatish Balay     ierr = PetscGetProgramName(pname,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
225e5c89e4eSSatish Balay     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"%s on a %s, %d proc. with options:\n",pname,arch,size);CHKERRQ(ierr);
22688c29154SBarry Smith     ierr = PetscViewerASCIIOpenWithFILE(PETSC_COMM_WORLD,*fd,&viewer);CHKERRQ(ierr);
22788c29154SBarry Smith     ierr = PetscOptionsView(viewer);CHKERRQ(ierr);
2286bf464f9SBarry Smith     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
229e5c89e4eSSatish Balay     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr);
230f56c2debSBarry Smith     err = fflush(*fd);
231e32f2f54SBarry Smith     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
232e5c89e4eSSatish Balay   }
233e5c89e4eSSatish Balay   PetscFunctionReturn(0);
234e5c89e4eSSatish Balay }
235e5c89e4eSSatish Balay 
236e5c89e4eSSatish Balay #undef __FUNCT__
237f3dea69dSBarry Smith #define __FUNCT__ "PetscCloseHistoryFile"
2387087cfbeSBarry Smith PetscErrorCode  PetscCloseHistoryFile(FILE **fd)
239e5c89e4eSSatish Balay {
240e5c89e4eSSatish Balay   PetscErrorCode ierr;
241e5c89e4eSSatish Balay   PetscMPIInt    rank;
242e5c89e4eSSatish Balay   char           date[64];
243f56c2debSBarry Smith   int            err;
244e5c89e4eSSatish Balay 
245e5c89e4eSSatish Balay   PetscFunctionBegin;
246e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
247e5c89e4eSSatish Balay   if (!rank) {
248e5c89e4eSSatish Balay     ierr = PetscGetDate(date,64);CHKERRQ(ierr);
249e5c89e4eSSatish Balay     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr);
250e5c89e4eSSatish Balay     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"Finished at %s\n",date);CHKERRQ(ierr);
251e5c89e4eSSatish Balay     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr);
252f56c2debSBarry Smith     err = fflush(*fd);
253e32f2f54SBarry Smith     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
254f56c2debSBarry Smith     err = fclose(*fd);
255e32f2f54SBarry Smith     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
256e5c89e4eSSatish Balay   }
257e5c89e4eSSatish Balay   PetscFunctionReturn(0);
258e5c89e4eSSatish Balay }
259e5c89e4eSSatish Balay 
260e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/
261e5c89e4eSSatish Balay 
262e5c89e4eSSatish Balay /*
263e5c89e4eSSatish Balay    This is ugly and probably belongs somewhere else, but I want to
264e5c89e4eSSatish Balay   be able to put a true MPI abort error handler with command line args.
265e5c89e4eSSatish Balay 
266e5c89e4eSSatish Balay     This is so MPI errors in the debugger will leave all the stack
2673c311c98SBarry Smith   frames. The default MP_Abort() cleans up and exits thus providing no useful information
2683c311c98SBarry Smith   in the debugger hence we call abort() instead of MPI_Abort().
269e5c89e4eSSatish Balay */
270e5c89e4eSSatish Balay 
271e5c89e4eSSatish Balay #undef __FUNCT__
272e5c89e4eSSatish Balay #define __FUNCT__ "Petsc_MPI_AbortOnError"
273e5c89e4eSSatish Balay void Petsc_MPI_AbortOnError(MPI_Comm *comm,PetscMPIInt *flag)
274e5c89e4eSSatish Balay {
275e5c89e4eSSatish Balay   PetscFunctionBegin;
2763c311c98SBarry Smith   (*PetscErrorPrintf)("MPI error %d\n",*flag);
277e5c89e4eSSatish Balay   abort();
278e5c89e4eSSatish Balay }
279e5c89e4eSSatish Balay 
280e5c89e4eSSatish Balay #undef __FUNCT__
281e5c89e4eSSatish Balay #define __FUNCT__ "Petsc_MPI_DebuggerOnError"
282e5c89e4eSSatish Balay void Petsc_MPI_DebuggerOnError(MPI_Comm *comm,PetscMPIInt *flag)
283e5c89e4eSSatish Balay {
284e5c89e4eSSatish Balay   PetscErrorCode ierr;
285e5c89e4eSSatish Balay 
286e5c89e4eSSatish Balay   PetscFunctionBegin;
2873c311c98SBarry Smith   (*PetscErrorPrintf)("MPI error %d\n",*flag);
288e5c89e4eSSatish Balay   ierr = PetscAttachDebugger();
289e5c89e4eSSatish Balay   if (ierr) { /* hopeless so get out */
2903c311c98SBarry Smith     MPI_Abort(*comm,*flag);
291e5c89e4eSSatish Balay   }
292e5c89e4eSSatish Balay }
293e5c89e4eSSatish Balay 
294e5c89e4eSSatish Balay #undef __FUNCT__
295e5c89e4eSSatish Balay #define __FUNCT__ "PetscEnd"
296e5c89e4eSSatish Balay /*@C
297e5c89e4eSSatish Balay    PetscEnd - Calls PetscFinalize() and then ends the program. This is useful if one
298e5c89e4eSSatish Balay      wishes a clean exit somewhere deep in the program.
299e5c89e4eSSatish Balay 
300e5c89e4eSSatish Balay    Collective on PETSC_COMM_WORLD
301e5c89e4eSSatish Balay 
302e5c89e4eSSatish Balay    Options Database Keys are the same as for PetscFinalize()
303e5c89e4eSSatish Balay 
304e5c89e4eSSatish Balay    Level: advanced
305e5c89e4eSSatish Balay 
306e5c89e4eSSatish Balay    Note:
307e5c89e4eSSatish Balay    See PetscInitialize() for more general runtime options.
308e5c89e4eSSatish Balay 
30988c29154SBarry Smith .seealso: PetscInitialize(), PetscOptionsView(), PetscMallocDump(), PetscMPIDump(), PetscFinalize()
310e5c89e4eSSatish Balay @*/
3117087cfbeSBarry Smith PetscErrorCode  PetscEnd(void)
312e5c89e4eSSatish Balay {
313e5c89e4eSSatish Balay   PetscFunctionBegin;
314e5c89e4eSSatish Balay   PetscFinalize();
315e5c89e4eSSatish Balay   exit(0);
316e5c89e4eSSatish Balay   return 0;
317e5c89e4eSSatish Balay }
318e5c89e4eSSatish Balay 
319ace3abfcSBarry Smith PetscBool    PetscOptionsPublish = PETSC_FALSE;
32009573ac7SBarry Smith extern PetscErrorCode        PetscSetUseTrMalloc_Private(void);
321ace3abfcSBarry Smith extern PetscBool  petscsetmallocvisited;
322e5c89e4eSSatish Balay static char       emacsmachinename[256];
323e5c89e4eSSatish Balay 
324e5c89e4eSSatish Balay PetscErrorCode (*PetscExternalVersionFunction)(MPI_Comm) = 0;
325e5c89e4eSSatish Balay PetscErrorCode (*PetscExternalHelpFunction)(MPI_Comm)    = 0;
326e5c89e4eSSatish Balay 
327e5c89e4eSSatish Balay #undef __FUNCT__
328e5c89e4eSSatish Balay #define __FUNCT__ "PetscSetHelpVersionFunctions"
329e5c89e4eSSatish Balay /*@C
330e5c89e4eSSatish Balay    PetscSetHelpVersionFunctions - Sets functions that print help and version information
331e5c89e4eSSatish Balay    before the PETSc help and version information is printed. Must call BEFORE PetscInitialize().
332e5c89e4eSSatish Balay    This routine enables a "higher-level" package that uses PETSc to print its messages first.
333e5c89e4eSSatish Balay 
334e5c89e4eSSatish Balay    Input Parameter:
335e5c89e4eSSatish Balay +  help - the help function (may be PETSC_NULL)
336da93591fSBarry Smith -  version - the version function (may be PETSC_NULL)
337e5c89e4eSSatish Balay 
338e5c89e4eSSatish Balay    Level: developer
339e5c89e4eSSatish Balay 
340e5c89e4eSSatish Balay    Concepts: package help message
341e5c89e4eSSatish Balay 
342e5c89e4eSSatish Balay @*/
3437087cfbeSBarry Smith PetscErrorCode  PetscSetHelpVersionFunctions(PetscErrorCode (*help)(MPI_Comm),PetscErrorCode (*version)(MPI_Comm))
344e5c89e4eSSatish Balay {
345e5c89e4eSSatish Balay   PetscFunctionBegin;
346e5c89e4eSSatish Balay   PetscExternalHelpFunction    = help;
347e5c89e4eSSatish Balay   PetscExternalVersionFunction = version;
348e5c89e4eSSatish Balay   PetscFunctionReturn(0);
349e5c89e4eSSatish Balay }
350e5c89e4eSSatish Balay 
351e5c89e4eSSatish Balay #undef __FUNCT__
352e5c89e4eSSatish Balay #define __FUNCT__ "PetscOptionsCheckInitial_Private"
3537087cfbeSBarry Smith PetscErrorCode  PetscOptionsCheckInitial_Private(void)
354e5c89e4eSSatish Balay {
355e5c89e4eSSatish Balay   char           string[64],mname[PETSC_MAX_PATH_LEN],*f;
356e5c89e4eSSatish Balay   MPI_Comm       comm = PETSC_COMM_WORLD;
357ace3abfcSBarry Smith   PetscBool      flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE,flg4 = PETSC_FALSE,flag,flgz,flgzout;
358e5c89e4eSSatish Balay   PetscErrorCode ierr;
359a6d0e24fSJed Brown   PetscReal      si;
360e5c89e4eSSatish Balay   int            i;
361e5c89e4eSSatish Balay   PetscMPIInt    rank;
362e5c89e4eSSatish Balay   char           version[256];
363e5c89e4eSSatish Balay 
364e5c89e4eSSatish Balay   PetscFunctionBegin;
365e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
366e5c89e4eSSatish Balay 
367e5c89e4eSSatish Balay   /*
368e5c89e4eSSatish Balay       Setup the memory management; support for tracing malloc() usage
369e5c89e4eSSatish Balay   */
3708bb29257SSatish Balay   ierr = PetscOptionsHasName(PETSC_NULL,"-malloc_log",&flg3);CHKERRQ(ierr);
37181b192fdSBarry Smith #if defined(PETSC_USE_DEBUG) && !defined(PETSC_USE_PTHREAD)
372acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc",&flg1,&flg2);CHKERRQ(ierr);
373e5c89e4eSSatish Balay   if ((!flg2 || flg1) && !petscsetmallocvisited) {
374555d055bSBarry Smith #if defined(PETSC_HAVE_VALGRIND)
375555d055bSBarry Smith     if (flg2 || !(RUNNING_ON_VALGRIND)) {
376555d055bSBarry Smith       /* turn off default -malloc if valgrind is being used */
377555d055bSBarry Smith #endif
378e5c89e4eSSatish Balay       ierr = PetscSetUseTrMalloc_Private();CHKERRQ(ierr);
379555d055bSBarry Smith #if defined(PETSC_HAVE_VALGRIND)
380555d055bSBarry Smith     }
381555d055bSBarry Smith #endif
382e5c89e4eSSatish Balay   }
383e5c89e4eSSatish Balay #else
384acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_dump",&flg1,PETSC_NULL);CHKERRQ(ierr);
385acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc",&flg2,PETSC_NULL);CHKERRQ(ierr);
386e5c89e4eSSatish Balay   if (flg1 || flg2 || flg3) {ierr = PetscSetUseTrMalloc_Private();CHKERRQ(ierr);}
387e5c89e4eSSatish Balay #endif
388e5c89e4eSSatish Balay   if (flg3) {
389e5c89e4eSSatish Balay     ierr = PetscMallocSetDumpLog();CHKERRQ(ierr);
390e5c89e4eSSatish Balay   }
39190d69ab7SBarry Smith   flg1 = PETSC_FALSE;
392acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_debug",&flg1,PETSC_NULL);CHKERRQ(ierr);
393e5c89e4eSSatish Balay   if (flg1) {
394e5c89e4eSSatish Balay     ierr = PetscSetUseTrMalloc_Private();CHKERRQ(ierr);
395e5c89e4eSSatish Balay     ierr = PetscMallocDebug(PETSC_TRUE);CHKERRQ(ierr);
396e5c89e4eSSatish Balay   }
397e5c89e4eSSatish Balay 
39890d69ab7SBarry Smith   flg1 = PETSC_FALSE;
399acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_info",&flg1,PETSC_NULL);CHKERRQ(ierr);
4007783f70dSSatish Balay   if (!flg1) {
40190d69ab7SBarry Smith     flg1 = PETSC_FALSE;
402acfcf0e5SJed Brown     ierr = PetscOptionsGetBool(PETSC_NULL,"-memory_info",&flg1,PETSC_NULL);CHKERRQ(ierr);
4037783f70dSSatish Balay   }
404e5c89e4eSSatish Balay   if (flg1) {
405e5c89e4eSSatish Balay     ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
406e5c89e4eSSatish Balay   }
407e5c89e4eSSatish Balay 
408e5c89e4eSSatish Balay   /*
409e5c89e4eSSatish Balay       Set the display variable for graphics
410e5c89e4eSSatish Balay   */
411e5c89e4eSSatish Balay   ierr = PetscSetDisplay();CHKERRQ(ierr);
412e5c89e4eSSatish Balay 
413e5c89e4eSSatish Balay   /*
41451dcc849SKerry Stevens       Determine whether user specified maximum number of threads
41551dcc849SKerry Stevens    */
41651dcc849SKerry Stevens   ierr = PetscOptionsHasName(PETSC_NULL,"-thread_max",&flg1);CHKERRQ(ierr);
41751dcc849SKerry Stevens   if(flg1) {
41851dcc849SKerry Stevens     ierr = PetscOptionsGetInt(PETSC_NULL,"-thread_max",&PetscMaxThreads,PETSC_NULL);CHKERRQ(ierr);
41951dcc849SKerry Stevens   }
42051dcc849SKerry Stevens 
42151dcc849SKerry Stevens   /*
42251dcc849SKerry Stevens       Determine whether to use thread pool
42351dcc849SKerry Stevens    */
42451dcc849SKerry Stevens   ierr = PetscOptionsHasName(PETSC_NULL,"-use_thread_pool",&flg1);CHKERRQ(ierr);
42551dcc849SKerry Stevens   if(flg1) {
42651dcc849SKerry Stevens     PetscUseThreadPool = PETSC_TRUE;
42751d315f7SKerry Stevens     PetscInt N_CORES = get_nprocs();
42851d315f7SKerry Stevens     ThreadCoreAffinity = (int*)malloc(N_CORES*sizeof(int));
42951d315f7SKerry Stevens     char tstr[9];
43051d315f7SKerry Stevens     char tbuf[2];
43151d315f7SKerry Stevens     strcpy(tstr,"-thread");
43251d315f7SKerry Stevens     for(i=0;i<PetscMaxThreads;i++) {
433*ba61063dSBarry Smith       ThreadCoreAffinity[i] = i;
43451d315f7SKerry Stevens       sprintf(tbuf,"%d",i);
43551d315f7SKerry Stevens       strcat(tstr,tbuf);
43651d315f7SKerry Stevens       ierr = PetscOptionsHasName(PETSC_NULL,tstr,&flg1);CHKERRQ(ierr);
43751d315f7SKerry Stevens       if(flg1) {
43851d315f7SKerry Stevens         ierr = PetscOptionsGetInt(PETSC_NULL,tstr,&ThreadCoreAffinity[i],PETSC_NULL);CHKERRQ(ierr);
439*ba61063dSBarry Smith         ThreadCoreAffinity[i] = ThreadCoreAffinity[i]%N_CORES; /* check on the user */
44051d315f7SKerry Stevens       }
44151d315f7SKerry Stevens       tstr[7] = '\0';
44251d315f7SKerry Stevens     }
443*ba61063dSBarry Smith     /* get the thread pool type */
44451d315f7SKerry Stevens     PetscInt ipool = 0;
44551d315f7SKerry Stevens     ierr = PetscOptionsGetInt(PETSC_NULL,"-pool",&ipool,PETSC_NULL);CHKERRQ(ierr);
44651d315f7SKerry Stevens     switch(ipool) {
44751d315f7SKerry Stevens     case 1:
44851d315f7SKerry Stevens       PetscThreadFunc       = &PetscThreadFunc_Tree;
44951d315f7SKerry Stevens       PetscThreadInitialize = &PetscThreadInitialize_Tree;
45051d315f7SKerry Stevens       PetscThreadFinalize   = &PetscThreadFinalize_Tree;
45151d315f7SKerry Stevens       MainWait              = &MainWait_Tree;
45251d315f7SKerry Stevens       MainJob               = &MainJob_Tree;
45351d315f7SKerry Stevens       break;
45451d315f7SKerry Stevens     case 2:
45551d315f7SKerry Stevens       PetscThreadFunc       = &PetscThreadFunc_Main;
45651d315f7SKerry Stevens       PetscThreadInitialize = &PetscThreadInitialize_Main;
45751d315f7SKerry Stevens       PetscThreadFinalize   = &PetscThreadFinalize_Main;
45851d315f7SKerry Stevens       MainWait              = &MainWait_Main;
45951d315f7SKerry Stevens       MainJob               = &MainJob_Main;
46051d315f7SKerry Stevens       break;
46151d315f7SKerry Stevens     case 3:
46251d315f7SKerry Stevens       PetscThreadFunc       = &PetscThreadFunc_Chain;
46351d315f7SKerry Stevens       PetscThreadInitialize = &PetscThreadInitialize_Chain;
46451d315f7SKerry Stevens       PetscThreadFinalize   = &PetscThreadFinalize_Chain;
46551d315f7SKerry Stevens       MainWait              = &MainWait_Chain;
46651d315f7SKerry Stevens       MainJob               = &MainJob_Chain;
46751d315f7SKerry Stevens       break;
46851d315f7SKerry Stevens     default:
46951d315f7SKerry Stevens       PetscThreadFunc       = &PetscThreadFunc_True;
47051d315f7SKerry Stevens       PetscThreadInitialize = &PetscThreadInitialize_True;
47151d315f7SKerry Stevens       PetscThreadFinalize   = &PetscThreadFinalize_True;
47251d315f7SKerry Stevens       MainWait              = &MainWait_True;
47351d315f7SKerry Stevens       MainJob               = &MainJob_True;
47451d315f7SKerry Stevens       break;
47551d315f7SKerry Stevens     }
47651dcc849SKerry Stevens   }
4770ca81413SKerry Stevens   PetscThreadInitialize(PetscMaxThreads);
47851dcc849SKerry Stevens   /*
479e5c89e4eSSatish Balay       Print the PETSc version information
480e5c89e4eSSatish Balay   */
481e5c89e4eSSatish Balay   ierr = PetscOptionsHasName(PETSC_NULL,"-v",&flg1);CHKERRQ(ierr);
482e5c89e4eSSatish Balay   ierr = PetscOptionsHasName(PETSC_NULL,"-version",&flg2);CHKERRQ(ierr);
483e5c89e4eSSatish Balay   ierr = PetscOptionsHasName(PETSC_NULL,"-help",&flg3);CHKERRQ(ierr);
484e5c89e4eSSatish Balay   if (flg1 || flg2 || flg3){
485e5c89e4eSSatish Balay 
486e5c89e4eSSatish Balay     /*
487e5c89e4eSSatish Balay        Print "higher-level" package version message
488e5c89e4eSSatish Balay     */
489e5c89e4eSSatish Balay     if (PetscExternalVersionFunction) {
490e5c89e4eSSatish Balay       ierr = (*PetscExternalVersionFunction)(comm);CHKERRQ(ierr);
491e5c89e4eSSatish Balay     }
492e5c89e4eSSatish Balay 
493a523d312SBarry Smith     ierr = PetscGetVersion(version,256);CHKERRQ(ierr);
494e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"--------------------------------------------\
495e5c89e4eSSatish Balay ------------------------------\n");CHKERRQ(ierr);
496e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"%s\n",version);CHKERRQ(ierr);
497e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"%s",PETSC_AUTHOR_INFO);CHKERRQ(ierr);
498e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"See docs/changes/index.html for recent updates.\n");CHKERRQ(ierr);
49984e42920SBarry Smith     ierr = (*PetscHelpPrintf)(comm,"See docs/faq.html for problems.\n");CHKERRQ(ierr);
500e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"See docs/manualpages/index.html for help. \n");CHKERRQ(ierr);
501e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"Libraries linked from %s\n",PETSC_LIB_DIR);CHKERRQ(ierr);
502e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"--------------------------------------------\
503e5c89e4eSSatish Balay ------------------------------\n");CHKERRQ(ierr);
504e5c89e4eSSatish Balay   }
505e5c89e4eSSatish Balay 
506e5c89e4eSSatish Balay   /*
507e5c89e4eSSatish Balay        Print "higher-level" package help message
508e5c89e4eSSatish Balay   */
509e5c89e4eSSatish Balay   if (flg3){
510e5c89e4eSSatish Balay     if (PetscExternalHelpFunction) {
511e5c89e4eSSatish Balay       ierr = (*PetscExternalHelpFunction)(comm);CHKERRQ(ierr);
512e5c89e4eSSatish Balay     }
513e5c89e4eSSatish Balay   }
514e5c89e4eSSatish Balay 
515e5c89e4eSSatish Balay   /*
516e5c89e4eSSatish Balay       Setup the error handling
517e5c89e4eSSatish Balay   */
51890d69ab7SBarry Smith   flg1 = PETSC_FALSE;
519acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-on_error_abort",&flg1,PETSC_NULL);CHKERRQ(ierr);
520cb9801acSJed Brown   if (flg1) { ierr = PetscPushErrorHandler(PetscAbortErrorHandler,0);CHKERRQ(ierr);}
52190d69ab7SBarry Smith   flg1 = PETSC_FALSE;
522acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-on_error_mpiabort",&flg1,PETSC_NULL);CHKERRQ(ierr);
523cb9801acSJed Brown   if (flg1) { ierr = PetscPushErrorHandler(PetscMPIAbortErrorHandler,0);CHKERRQ(ierr);}
52490d69ab7SBarry Smith   flg1 = PETSC_FALSE;
525acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-mpi_return_on_error",&flg1,PETSC_NULL);CHKERRQ(ierr);
526e5c89e4eSSatish Balay   if (flg1) {
527e5c89e4eSSatish Balay     ierr = MPI_Errhandler_set(comm,MPI_ERRORS_RETURN);CHKERRQ(ierr);
528e5c89e4eSSatish Balay   }
52990d69ab7SBarry Smith   flg1 = PETSC_FALSE;
530acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-no_signal_handler",&flg1,PETSC_NULL);CHKERRQ(ierr);
531cb9801acSJed Brown   if (!flg1) {ierr = PetscPushSignalHandler(PetscDefaultSignalHandler,(void*)0);CHKERRQ(ierr);}
53296cc47afSJed Brown   flg1 = PETSC_FALSE;
533acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-fp_trap",&flg1,PETSC_NULL);CHKERRQ(ierr);
53496cc47afSJed Brown   if (flg1) {ierr = PetscSetFPTrap(PETSC_FP_TRAP_ON);CHKERRQ(ierr);}
535e5c89e4eSSatish Balay 
536e5c89e4eSSatish Balay   /*
537e5c89e4eSSatish Balay       Setup debugger information
538e5c89e4eSSatish Balay   */
539e5c89e4eSSatish Balay   ierr = PetscSetDefaultDebugger();CHKERRQ(ierr);
540e5c89e4eSSatish Balay   ierr = PetscOptionsGetString(PETSC_NULL,"-on_error_attach_debugger",string,64,&flg1);CHKERRQ(ierr);
541e5c89e4eSSatish Balay   if (flg1) {
542e5c89e4eSSatish Balay     MPI_Errhandler err_handler;
543e5c89e4eSSatish Balay 
544e5c89e4eSSatish Balay     ierr = PetscSetDebuggerFromString(string);CHKERRQ(ierr);
545e5c89e4eSSatish Balay     ierr = MPI_Errhandler_create((MPI_Handler_function*)Petsc_MPI_DebuggerOnError,&err_handler);CHKERRQ(ierr);
546e5c89e4eSSatish Balay     ierr = MPI_Errhandler_set(comm,err_handler);CHKERRQ(ierr);
547e5c89e4eSSatish Balay     ierr = PetscPushErrorHandler(PetscAttachDebuggerErrorHandler,0);CHKERRQ(ierr);
548e5c89e4eSSatish Balay   }
5495e96ac45SJed Brown   ierr = PetscOptionsGetString(PETSC_NULL,"-debug_terminal",string,64,&flg1);CHKERRQ(ierr);
5505e96ac45SJed Brown   if (flg1) { ierr = PetscSetDebugTerminal(string);CHKERRQ(ierr); }
551e5c89e4eSSatish Balay   ierr = PetscOptionsGetString(PETSC_NULL,"-start_in_debugger",string,64,&flg1);CHKERRQ(ierr);
552e5c89e4eSSatish Balay   ierr = PetscOptionsGetString(PETSC_NULL,"-stop_for_debugger",string,64,&flg2);CHKERRQ(ierr);
553e5c89e4eSSatish Balay   if (flg1 || flg2) {
554e5c89e4eSSatish Balay     PetscMPIInt    size;
555e5c89e4eSSatish Balay     PetscInt       lsize,*nodes;
556e5c89e4eSSatish Balay     MPI_Errhandler err_handler;
557e5c89e4eSSatish Balay     /*
558e5c89e4eSSatish Balay        we have to make sure that all processors have opened
559e5c89e4eSSatish Balay        connections to all other processors, otherwise once the
560e5c89e4eSSatish Balay        debugger has stated it is likely to receive a SIGUSR1
561e5c89e4eSSatish Balay        and kill the program.
562e5c89e4eSSatish Balay     */
563e5c89e4eSSatish Balay     ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
564e5c89e4eSSatish Balay     if (size > 2) {
565533163c2SBarry Smith       PetscMPIInt dummy = 0;
566e5c89e4eSSatish Balay       MPI_Status  status;
567e5c89e4eSSatish Balay       for (i=0; i<size; i++) {
568e5c89e4eSSatish Balay         if (rank != i) {
569e5c89e4eSSatish Balay           ierr = MPI_Send(&dummy,1,MPI_INT,i,109,PETSC_COMM_WORLD);CHKERRQ(ierr);
570e5c89e4eSSatish Balay         }
571e5c89e4eSSatish Balay       }
572e5c89e4eSSatish Balay       for (i=0; i<size; i++) {
573e5c89e4eSSatish Balay         if (rank != i) {
574e5c89e4eSSatish Balay           ierr = MPI_Recv(&dummy,1,MPI_INT,i,109,PETSC_COMM_WORLD,&status);CHKERRQ(ierr);
575e5c89e4eSSatish Balay         }
576e5c89e4eSSatish Balay       }
577e5c89e4eSSatish Balay     }
578e5c89e4eSSatish Balay     /* check if this processor node should be in debugger */
579e5c89e4eSSatish Balay     ierr  = PetscMalloc(size*sizeof(PetscInt),&nodes);CHKERRQ(ierr);
580e5c89e4eSSatish Balay     lsize = size;
581e5c89e4eSSatish Balay     ierr  = PetscOptionsGetIntArray(PETSC_NULL,"-debugger_nodes",nodes,&lsize,&flag);CHKERRQ(ierr);
582e5c89e4eSSatish Balay     if (flag) {
583e5c89e4eSSatish Balay       for (i=0; i<lsize; i++) {
584e5c89e4eSSatish Balay         if (nodes[i] == rank) { flag = PETSC_FALSE; break; }
585e5c89e4eSSatish Balay       }
586e5c89e4eSSatish Balay     }
587e5c89e4eSSatish Balay     if (!flag) {
588e5c89e4eSSatish Balay       ierr = PetscSetDebuggerFromString(string);CHKERRQ(ierr);
589e5c89e4eSSatish Balay       ierr = PetscPushErrorHandler(PetscAbortErrorHandler,0);CHKERRQ(ierr);
590e5c89e4eSSatish Balay       if (flg1) {
591e5c89e4eSSatish Balay         ierr = PetscAttachDebugger();CHKERRQ(ierr);
592e5c89e4eSSatish Balay       } else {
593e5c89e4eSSatish Balay         ierr = PetscStopForDebugger();CHKERRQ(ierr);
594e5c89e4eSSatish Balay       }
595e5c89e4eSSatish Balay       ierr = MPI_Errhandler_create((MPI_Handler_function*)Petsc_MPI_AbortOnError,&err_handler);CHKERRQ(ierr);
596e5c89e4eSSatish Balay       ierr = MPI_Errhandler_set(comm,err_handler);CHKERRQ(ierr);
597e5c89e4eSSatish Balay     }
598e5c89e4eSSatish Balay     ierr = PetscFree(nodes);CHKERRQ(ierr);
599e5c89e4eSSatish Balay   }
600e5c89e4eSSatish Balay 
601e5c89e4eSSatish Balay   ierr = PetscOptionsGetString(PETSC_NULL,"-on_error_emacs",emacsmachinename,128,&flg1);CHKERRQ(ierr);
602cb9801acSJed Brown   if (flg1 && !rank) {ierr = PetscPushErrorHandler(PetscEmacsClientErrorHandler,emacsmachinename);CHKERRQ(ierr);}
603e5c89e4eSSatish Balay 
60493ba235fSBarry Smith #if defined(PETSC_USE_SOCKET_VIEWER)
60522b84c2fSbcordonn   /*
60622b84c2fSbcordonn     Activates new sockets for zope if needed
60722b84c2fSbcordonn   */
60884ab5442Sbcordonn   ierr = PetscOptionsHasName(PETSC_NULL,"-zope", &flgz);CHKERRQ(ierr);
609d8c6e182Sbcordonn   ierr = PetscOptionsHasName(PETSC_NULL,"-nostdout", &flgzout);CHKERRQ(ierr);
6106dc8fec2Sbcordonn   if (flgz){
61122b84c2fSbcordonn     int  sockfd;
612f1384234SBarry Smith     char hostname[256];
61322b84c2fSbcordonn     char username[256];
6146dc8fec2Sbcordonn     int  remoteport = 9999;
6159c4c166aSBarry Smith 
61684ab5442Sbcordonn     ierr = PetscOptionsGetString(PETSC_NULL, "-zope", hostname, 256, &flgz);CHKERRQ(ierr);
61784ab5442Sbcordonn     if (!hostname[0]){
6189c4c166aSBarry Smith       ierr = PetscGetHostName(hostname,256);CHKERRQ(ierr);
6199c4c166aSBarry Smith     }
62022b84c2fSbcordonn     ierr = PetscOpenSocket(hostname, remoteport, &sockfd);CHKERRQ(ierr);
6219c4c166aSBarry Smith     ierr = PetscGetUserName(username, 256);CHKERRQ(ierr);
62222b84c2fSbcordonn     PETSC_ZOPEFD = fdopen(sockfd, "w");
62322b84c2fSbcordonn     if (flgzout){
62422b84c2fSbcordonn       PETSC_STDOUT = PETSC_ZOPEFD;
625606f100bSbcordonn       fprintf(PETSC_STDOUT, "<<<user>>> %s\n",username);
6266dc8fec2Sbcordonn       fprintf(PETSC_STDOUT, "<<<start>>>");
6279c4c166aSBarry Smith     } else {
628d8c6e182Sbcordonn       fprintf(PETSC_ZOPEFD, "<<<user>>> %s\n",username);
629d8c6e182Sbcordonn       fprintf(PETSC_ZOPEFD, "<<<start>>>");
6309c4c166aSBarry Smith     }
6319c4c166aSBarry Smith   }
63293ba235fSBarry Smith #endif
633ffc871a5SBarry Smith #if defined(PETSC_USE_SERVER)
634ffc871a5SBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-server", &flgz);CHKERRQ(ierr);
635ffc871a5SBarry Smith   if (flgz){
636ffc871a5SBarry Smith     PetscInt port = PETSC_DECIDE;
637ffc871a5SBarry Smith     ierr = PetscOptionsGetInt(PETSC_NULL,"-server",&port,PETSC_NULL);CHKERRQ(ierr);
638ffc871a5SBarry Smith     ierr = PetscWebServe(PETSC_COMM_WORLD,(int)port);CHKERRQ(ierr);
639ffc871a5SBarry Smith   }
640ffc871a5SBarry Smith #endif
6416dc8fec2Sbcordonn 
642e5c89e4eSSatish Balay   /*
643e5c89e4eSSatish Balay         Setup profiling and logging
644e5c89e4eSSatish Balay   */
6456cf91177SBarry Smith #if defined (PETSC_USE_INFO)
6468bb29257SSatish Balay   {
647e5c89e4eSSatish Balay     char logname[PETSC_MAX_PATH_LEN]; logname[0] = 0;
6486cf91177SBarry Smith     ierr = PetscOptionsGetString(PETSC_NULL,"-info",logname,250,&flg1);CHKERRQ(ierr);
6498bb29257SSatish Balay     if (flg1 && logname[0]) {
650fcc2139eSBarry Smith       ierr = PetscInfoAllow(PETSC_TRUE,logname);CHKERRQ(ierr);
6518bb29257SSatish Balay     } else if (flg1) {
652fcc2139eSBarry Smith       ierr = PetscInfoAllow(PETSC_TRUE,PETSC_NULL);CHKERRQ(ierr);
653e5c89e4eSSatish Balay     }
654e5c89e4eSSatish Balay   }
655865f6aa8SSatish Balay #endif
656865f6aa8SSatish Balay #if defined(PETSC_USE_LOG)
657865f6aa8SSatish Balay   mname[0] = 0;
658f3dea69dSBarry Smith   ierr = PetscOptionsGetString(PETSC_NULL,"-history",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
659865f6aa8SSatish Balay   if (flg1) {
660865f6aa8SSatish Balay     if (mname[0]) {
661f3dea69dSBarry Smith       ierr = PetscOpenHistoryFile(mname,&petsc_history);CHKERRQ(ierr);
662865f6aa8SSatish Balay     } else {
663f3dea69dSBarry Smith       ierr = PetscOpenHistoryFile(0,&petsc_history);CHKERRQ(ierr);
664865f6aa8SSatish Balay     }
665865f6aa8SSatish Balay   }
666e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MPE)
66790d69ab7SBarry Smith   flg1 = PETSC_FALSE;
668fcfd50ebSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-log_mpe",&flg1);CHKERRQ(ierr);
669e5c89e4eSSatish Balay   if (flg1) PetscLogMPEBegin();
670e5c89e4eSSatish Balay #endif
67190d69ab7SBarry Smith   flg1 = PETSC_FALSE;
67290d69ab7SBarry Smith   flg2 = PETSC_FALSE;
67390d69ab7SBarry Smith   flg3 = PETSC_FALSE;
674acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-log_all",&flg1,PETSC_NULL);CHKERRQ(ierr);
675acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-log",&flg2,PETSC_NULL);CHKERRQ(ierr);
676d44e083bSSatish Balay   ierr = PetscOptionsHasName(PETSC_NULL,"-log_summary",&flg3);CHKERRQ(ierr);
6779f7b6320SBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-log_summary_python",&flg4);CHKERRQ(ierr);
678e5c89e4eSSatish Balay   if (flg1)                      {  ierr = PetscLogAllBegin();CHKERRQ(ierr); }
6799f7b6320SBarry Smith   else if (flg2 || flg3 || flg4) {  ierr = PetscLogBegin();CHKERRQ(ierr);}
680e5c89e4eSSatish Balay 
681e5c89e4eSSatish Balay   ierr = PetscOptionsGetString(PETSC_NULL,"-log_trace",mname,250,&flg1);CHKERRQ(ierr);
682e5c89e4eSSatish Balay   if (flg1) {
683e5c89e4eSSatish Balay     char name[PETSC_MAX_PATH_LEN],fname[PETSC_MAX_PATH_LEN];
684e5c89e4eSSatish Balay     FILE *file;
685e5c89e4eSSatish Balay     if (mname[0]) {
686e5c89e4eSSatish Balay       sprintf(name,"%s.%d",mname,rank);
687e5c89e4eSSatish Balay       ierr = PetscFixFilename(name,fname);CHKERRQ(ierr);
688e5c89e4eSSatish Balay       file = fopen(fname,"w");
689f3dea69dSBarry Smith       if (!file) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open trace file: %s",fname);
690e5c89e4eSSatish Balay     } else {
691da9f1d6bSBarry Smith       file = PETSC_STDOUT;
692e5c89e4eSSatish Balay     }
693e5c89e4eSSatish Balay     ierr = PetscLogTraceBegin(file);CHKERRQ(ierr);
694e5c89e4eSSatish Balay   }
695e5c89e4eSSatish Balay #endif
696e5c89e4eSSatish Balay 
697e5c89e4eSSatish Balay   /*
698e5c89e4eSSatish Balay       Setup building of stack frames for all function calls
699e5c89e4eSSatish Balay   */
70063d6bff0SBarry Smith #if defined(PETSC_USE_DEBUG) && !defined(PETSC_USE_PTHREAD)
701e5c89e4eSSatish Balay   ierr = PetscStackCreate();CHKERRQ(ierr);
702e5c89e4eSSatish Balay #endif
703e5c89e4eSSatish Balay 
704acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-options_gui",&PetscOptionsPublish,PETSC_NULL);CHKERRQ(ierr);
705e5c89e4eSSatish Balay 
706e5c89e4eSSatish Balay   /*
707e5c89e4eSSatish Balay        Print basic help message
708e5c89e4eSSatish Balay   */
709e5c89e4eSSatish Balay   ierr = PetscOptionsHasName(PETSC_NULL,"-help",&flg1);CHKERRQ(ierr);
710e5c89e4eSSatish Balay   if (flg1) {
711e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"Options for all PETSc programs:\n");CHKERRQ(ierr);
712301d30feSBarry Smith     ierr = (*PetscHelpPrintf)(comm," -help: prints help method for each option\n");CHKERRQ(ierr);
713301d30feSBarry Smith     ierr = (*PetscHelpPrintf)(comm," -on_error_abort: cause an abort when an error is detected. Useful \n ");CHKERRQ(ierr);
714301d30feSBarry Smith     ierr = (*PetscHelpPrintf)(comm,"       only when run in the debugger\n");CHKERRQ(ierr);
715e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -on_error_attach_debugger [gdb,dbx,xxgdb,ups,noxterm]\n");CHKERRQ(ierr);
716e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"       start the debugger in new xterm\n");CHKERRQ(ierr);
717e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"       unless noxterm is given\n");CHKERRQ(ierr);
718e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -start_in_debugger [gdb,dbx,xxgdb,ups,noxterm]\n");CHKERRQ(ierr);
719e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"       start all processes in the debugger\n");CHKERRQ(ierr);
720e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -on_error_emacs <machinename>\n");CHKERRQ(ierr);
721e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"    emacs jumps to error file\n");CHKERRQ(ierr);
722e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -debugger_nodes [n1,n2,..] Nodes to start in debugger\n");CHKERRQ(ierr);
723e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -debugger_pause [m] : delay (in seconds) to attach debugger\n");CHKERRQ(ierr);
724e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -stop_for_debugger : prints message on how to attach debugger manually\n");CHKERRQ(ierr);
725e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"                      waits the delay for you to attach\n");CHKERRQ(ierr);
726e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -display display: Location where graphics and debuggers are displayed\n");CHKERRQ(ierr);
727e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -no_signal_handler: do not trap error signals\n");CHKERRQ(ierr);
728e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -mpi_return_on_error: MPI returns error code, rather than abort on internal error\n");CHKERRQ(ierr);
729e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -fp_trap: stop on floating point exceptions\n");CHKERRQ(ierr);
730e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"           note on IBM RS6000 this slows run greatly\n");CHKERRQ(ierr);
731e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -malloc_dump <optional filename>: dump list of unfreed memory at conclusion\n");CHKERRQ(ierr);
732e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -malloc: use our error checking malloc\n");CHKERRQ(ierr);
733e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -malloc no: don't use error checking malloc\n");CHKERRQ(ierr);
7344161f2a3SBarry Smith     ierr = (*PetscHelpPrintf)(comm," -malloc_info: prints total memory usage\n");CHKERRQ(ierr);
7354161f2a3SBarry Smith     ierr = (*PetscHelpPrintf)(comm," -malloc_log: keeps log of all memory allocations\n");CHKERRQ(ierr);
736e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -malloc_debug: enables extended checking for memory corruption\n");CHKERRQ(ierr);
737e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -options_table: dump list of options inputted\n");CHKERRQ(ierr);
738e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -options_left: dump list of unused options\n");CHKERRQ(ierr);
739e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -options_left no: don't dump list of unused options\n");CHKERRQ(ierr);
740e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -tmp tmpdir: alternative /tmp directory\n");CHKERRQ(ierr);
741e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -shared_tmp: tmp directory is shared by all processors\n");CHKERRQ(ierr);
742a8c7a070SBarry Smith     ierr = (*PetscHelpPrintf)(comm," -not_shared_tmp: each processor has separate tmp directory\n");CHKERRQ(ierr);
743e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -memory_info: print memory usage at end of run\n");CHKERRQ(ierr);
744e5c89e4eSSatish Balay #if defined(PETSC_USE_LOG)
745e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -get_total_flops: total flops over all processors\n");CHKERRQ(ierr);
746e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -log[_all _summary]: logging objects and events\n");CHKERRQ(ierr);
747e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -log_trace [filename]: prints trace of all PETSc calls\n");CHKERRQ(ierr);
748e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MPE)
749e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -log_mpe: Also create logfile viewable through upshot\n");CHKERRQ(ierr);
750e5c89e4eSSatish Balay #endif
7516cf91177SBarry Smith     ierr = (*PetscHelpPrintf)(comm," -info <optional filename>: print informative messages about the calculations\n");CHKERRQ(ierr);
752e5c89e4eSSatish Balay #endif
753e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -v: prints PETSc version number and release date\n");CHKERRQ(ierr);
754e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -options_file <file>: reads options from file\n");CHKERRQ(ierr);
755e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm," -petsc_sleep n: sleeps n seconds before running program\n");CHKERRQ(ierr);
756e5c89e4eSSatish Balay     ierr = (*PetscHelpPrintf)(comm,"-----------------------------------------------\n");CHKERRQ(ierr);
757e5c89e4eSSatish Balay   }
758e5c89e4eSSatish Balay 
759a6d0e24fSJed Brown   ierr = PetscOptionsGetReal(PETSC_NULL,"-petsc_sleep",&si,&flg1);CHKERRQ(ierr);
760e5c89e4eSSatish Balay   if (flg1) {
761e5c89e4eSSatish Balay     ierr = PetscSleep(si);CHKERRQ(ierr);
762e5c89e4eSSatish Balay   }
763e5c89e4eSSatish Balay 
7646cf91177SBarry Smith   ierr = PetscOptionsGetString(PETSC_NULL,"-info_exclude",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
765e5c89e4eSSatish Balay   ierr = PetscStrstr(mname,"null",&f);CHKERRQ(ierr);
766e5c89e4eSSatish Balay   if (f) {
7676cf91177SBarry Smith     ierr = PetscInfoDeactivateClass(PETSC_NULL);CHKERRQ(ierr);
768e5c89e4eSSatish Balay   }
769827f890bSBarry Smith 
7708154be41SBarry Smith #if defined(PETSC_HAVE_CUSP)
771c97f9302SBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-log_summary",&flg3);CHKERRQ(ierr);
77273113deaSBarry Smith   if (flg3) flg1 = PETSC_TRUE;
77373113deaSBarry Smith   else flg1 = PETSC_FALSE;
7748154be41SBarry Smith   ierr = PetscOptionsGetBool(PETSC_NULL,"-cusp_synchronize",&flg1,PETSC_NULL);CHKERRQ(ierr);
7758154be41SBarry Smith   if (flg1) synchronizeCUSP = PETSC_TRUE;
776bab1f7e6SVictor Minden #endif
777192daf7cSBarry Smith 
778e5c89e4eSSatish Balay   PetscFunctionReturn(0);
779e5c89e4eSSatish Balay }
780df413903SBarry Smith 
781*ba61063dSBarry Smith #if defined(PETSC_USE_PTHREAD_CLASSES)
782*ba61063dSBarry Smith 
78351d315f7SKerry Stevens /**** 'Tree' Thread Pool Functions ****/
78451d315f7SKerry Stevens void* PetscThreadFunc_Tree(void* arg) {
78551d315f7SKerry Stevens   PetscErrorCode iterr;
78651d315f7SKerry Stevens   int icorr,ierr;
78751d315f7SKerry Stevens   int* pId = (int*)arg;
78851d315f7SKerry Stevens   int ThreadId = *pId,Mary = 2,i,SubWorker;
78951d315f7SKerry Stevens   PetscBool PeeOn;
79051d315f7SKerry Stevens   cpu_set_t mset;
79151d315f7SKerry Stevens 
79251d315f7SKerry Stevens   icorr = ThreadCoreAffinity[ThreadId];
79351d315f7SKerry Stevens   CPU_ZERO(&mset);
79451d315f7SKerry Stevens   CPU_SET(icorr,&mset);
79551d315f7SKerry Stevens   sched_setaffinity(0,sizeof(cpu_set_t),&mset);
79651d315f7SKerry Stevens 
79751d315f7SKerry Stevens   if((Mary*ThreadId+1)>(PetscMaxThreads-1)) {
79851d315f7SKerry Stevens     PeeOn = PETSC_TRUE;
79951d315f7SKerry Stevens   }
80051d315f7SKerry Stevens   else {
80151d315f7SKerry Stevens     PeeOn = PETSC_FALSE;
80251d315f7SKerry Stevens   }
80351d315f7SKerry Stevens   if(PeeOn==PETSC_FALSE) {
804*ba61063dSBarry Smith     /* check your subordinates, wait for them to be ready */
80551d315f7SKerry Stevens     for(i=1;i<=Mary;i++) {
80651d315f7SKerry Stevens       SubWorker = Mary*ThreadId+i;
80751d315f7SKerry Stevens       if(SubWorker<PetscMaxThreads) {
80851d315f7SKerry Stevens         ierr = pthread_mutex_lock(job_tree.mutexarray[SubWorker]);
80951d315f7SKerry Stevens         while(*(job_tree.arrThreadReady[SubWorker])==PETSC_FALSE) {
810*ba61063dSBarry Smith           /* upon entry, automically releases the lock and blocks
811*ba61063dSBarry Smith            upon return, has the lock */
81251d315f7SKerry Stevens           ierr = pthread_cond_wait(job_tree.cond1array[SubWorker],job_tree.mutexarray[SubWorker]);
81351d315f7SKerry Stevens         }
81451d315f7SKerry Stevens         ierr = pthread_mutex_unlock(job_tree.mutexarray[SubWorker]);
81551d315f7SKerry Stevens       }
81651d315f7SKerry Stevens     }
817*ba61063dSBarry Smith     /* your subordinates are now ready */
81851d315f7SKerry Stevens   }
81951d315f7SKerry Stevens   ierr = pthread_mutex_lock(job_tree.mutexarray[ThreadId]);
820*ba61063dSBarry Smith   /* update your ready status */
82151d315f7SKerry Stevens   *(job_tree.arrThreadReady[ThreadId]) = PETSC_TRUE;
82251d315f7SKerry Stevens   if(ThreadId==0) {
82351d315f7SKerry Stevens     job_tree.eJobStat = JobCompleted;
824*ba61063dSBarry Smith     /* ignal main */
82551d315f7SKerry Stevens     ierr = pthread_cond_signal(&main_cond);
82651d315f7SKerry Stevens   }
82751d315f7SKerry Stevens   else {
828*ba61063dSBarry Smith     /* tell your boss that you're ready to work */
82951d315f7SKerry Stevens     ierr = pthread_cond_signal(job_tree.cond1array[ThreadId]);
83051d315f7SKerry Stevens   }
831*ba61063dSBarry Smith   /* the while loop needs to have an exit
832*ba61063dSBarry Smith   the 'main' thread can terminate all the threads by performing a broadcast
833*ba61063dSBarry Smith    and calling FuncFinish */
83451d315f7SKerry Stevens   while(PetscThreadGo) {
835*ba61063dSBarry Smith     /*need to check the condition to ensure we don't have to wait
836*ba61063dSBarry Smith       waiting when you don't have to causes problems
837*ba61063dSBarry Smith      also need to check the condition to ensure proper handling of spurious wakeups */
83851d315f7SKerry Stevens     while(*(job_tree.arrThreadReady[ThreadId])==PETSC_TRUE) {
839*ba61063dSBarry Smith       /* upon entry, automically releases the lock and blocks
840*ba61063dSBarry Smith        upon return, has the lock */
84151d315f7SKerry Stevens         ierr = pthread_cond_wait(job_tree.cond2array[ThreadId],job_tree.mutexarray[ThreadId]);
84251d315f7SKerry Stevens 	*(job_tree.arrThreadStarted[ThreadId]) = PETSC_TRUE;
84351d315f7SKerry Stevens 	*(job_tree.arrThreadReady[ThreadId])   = PETSC_FALSE;
84451d315f7SKerry Stevens     }
84551d315f7SKerry Stevens     if(ThreadId==0) {
84651d315f7SKerry Stevens       job_tree.startJob = PETSC_FALSE;
84751d315f7SKerry Stevens       job_tree.eJobStat = ThreadsWorking;
84851d315f7SKerry Stevens     }
84951d315f7SKerry Stevens     ierr = pthread_mutex_unlock(job_tree.mutexarray[ThreadId]);
85051d315f7SKerry Stevens     if(PeeOn==PETSC_FALSE) {
851*ba61063dSBarry Smith       /* tell your subordinates it's time to get to work */
85251d315f7SKerry Stevens       for(i=1; i<=Mary; i++) {
85351d315f7SKerry Stevens 	SubWorker = Mary*ThreadId+i;
85451d315f7SKerry Stevens         if(SubWorker<PetscMaxThreads) {
85551d315f7SKerry Stevens           ierr = pthread_cond_signal(job_tree.cond2array[SubWorker]);
85651d315f7SKerry Stevens         }
85751d315f7SKerry Stevens       }
85851d315f7SKerry Stevens     }
859*ba61063dSBarry Smith     /* do your job */
86051d315f7SKerry Stevens     if(job_tree.pdata==NULL) {
86151d315f7SKerry Stevens       iterr = (PetscErrorCode)(long int)job_tree.pfunc(job_tree.pdata);
86251d315f7SKerry Stevens     }
86351d315f7SKerry Stevens     else {
86451d315f7SKerry Stevens       iterr = (PetscErrorCode)(long int)job_tree.pfunc(job_tree.pdata[ThreadId]);
86551d315f7SKerry Stevens     }
86651d315f7SKerry Stevens     if(iterr!=0) {
86751d315f7SKerry Stevens       ithreaderr = 1;
86851d315f7SKerry Stevens     }
86951d315f7SKerry Stevens     if(PetscThreadGo) {
870*ba61063dSBarry Smith       /* reset job, get ready for more */
87151d315f7SKerry Stevens       if(PeeOn==PETSC_FALSE) {
872*ba61063dSBarry Smith         /* check your subordinates, waiting for them to be ready
873*ba61063dSBarry Smith          how do you know for a fact that a given subordinate has actually started? */
87451d315f7SKerry Stevens 	for(i=1;i<=Mary;i++) {
87551d315f7SKerry Stevens 	  SubWorker = Mary*ThreadId+i;
87651d315f7SKerry Stevens           if(SubWorker<PetscMaxThreads) {
87751d315f7SKerry Stevens             ierr = pthread_mutex_lock(job_tree.mutexarray[SubWorker]);
87851d315f7SKerry Stevens             while(*(job_tree.arrThreadReady[SubWorker])==PETSC_FALSE||*(job_tree.arrThreadStarted[SubWorker])==PETSC_FALSE) {
879*ba61063dSBarry Smith               /* upon entry, automically releases the lock and blocks
880*ba61063dSBarry Smith                upon return, has the lock */
88151d315f7SKerry Stevens               ierr = pthread_cond_wait(job_tree.cond1array[SubWorker],job_tree.mutexarray[SubWorker]);
88251d315f7SKerry Stevens             }
88351d315f7SKerry Stevens             ierr = pthread_mutex_unlock(job_tree.mutexarray[SubWorker]);
88451d315f7SKerry Stevens           }
88551d315f7SKerry Stevens 	}
886*ba61063dSBarry Smith         /* your subordinates are now ready */
88751d315f7SKerry Stevens       }
88851d315f7SKerry Stevens       ierr = pthread_mutex_lock(job_tree.mutexarray[ThreadId]);
88951d315f7SKerry Stevens       *(job_tree.arrThreadReady[ThreadId]) = PETSC_TRUE;
89051d315f7SKerry Stevens       if(ThreadId==0) {
891*ba61063dSBarry Smith 	job_tree.eJobStat = JobCompleted; /* oot thread: last thread to complete, guaranteed! */
892*ba61063dSBarry Smith         /* root thread signals 'main' */
89351d315f7SKerry Stevens         ierr = pthread_cond_signal(&main_cond);
89451d315f7SKerry Stevens       }
89551d315f7SKerry Stevens       else {
896*ba61063dSBarry Smith         /* signal your boss before you go to sleep */
89751d315f7SKerry Stevens         ierr = pthread_cond_signal(job_tree.cond1array[ThreadId]);
89851d315f7SKerry Stevens       }
89951d315f7SKerry Stevens     }
90051d315f7SKerry Stevens   }
90151d315f7SKerry Stevens   return NULL;
90251d315f7SKerry Stevens }
90351d315f7SKerry Stevens 
90451d315f7SKerry Stevens #undef __FUNCT__
90551d315f7SKerry Stevens #define __FUNCT__ "PetscThreadInitialize_Tree"
90651d315f7SKerry Stevens void* PetscThreadInitialize_Tree(PetscInt N) {
90751d315f7SKerry Stevens   PetscInt i,ierr;
90851d315f7SKerry Stevens   int status;
90951d315f7SKerry Stevens 
91051d315f7SKerry Stevens   if(PetscUseThreadPool) {
91151d315f7SKerry Stevens     size_t Val1 = (size_t)CACHE_LINE_SIZE;
91251d315f7SKerry Stevens     size_t Val2 = (size_t)PetscMaxThreads*CACHE_LINE_SIZE;
91351d315f7SKerry Stevens     arrmutex = (char*)memalign(Val1,Val2);
91451d315f7SKerry Stevens     arrcond1 = (char*)memalign(Val1,Val2);
91551d315f7SKerry Stevens     arrcond2 = (char*)memalign(Val1,Val2);
91651d315f7SKerry Stevens     arrstart = (char*)memalign(Val1,Val2);
91751d315f7SKerry Stevens     arrready = (char*)memalign(Val1,Val2);
91851d315f7SKerry Stevens     job_tree.mutexarray       = (pthread_mutex_t**)malloc(PetscMaxThreads*sizeof(pthread_mutex_t*));
91951d315f7SKerry Stevens     job_tree.cond1array       = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*));
92051d315f7SKerry Stevens     job_tree.cond2array       = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*));
92151d315f7SKerry Stevens     job_tree.arrThreadStarted = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*));
92251d315f7SKerry Stevens     job_tree.arrThreadReady   = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*));
923*ba61063dSBarry Smith     /* initialize job structure */
92451d315f7SKerry Stevens     for(i=0; i<PetscMaxThreads; i++) {
92551d315f7SKerry Stevens       job_tree.mutexarray[i]        = (pthread_mutex_t*)(arrmutex+CACHE_LINE_SIZE*i);
92651d315f7SKerry Stevens       job_tree.cond1array[i]        = (pthread_cond_t*)(arrcond1+CACHE_LINE_SIZE*i);
92751d315f7SKerry Stevens       job_tree.cond2array[i]        = (pthread_cond_t*)(arrcond2+CACHE_LINE_SIZE*i);
92851d315f7SKerry Stevens       job_tree.arrThreadStarted[i]  = (PetscBool*)(arrstart+CACHE_LINE_SIZE*i);
92951d315f7SKerry Stevens       job_tree.arrThreadReady[i]    = (PetscBool*)(arrready+CACHE_LINE_SIZE*i);
93051d315f7SKerry Stevens     }
93151d315f7SKerry Stevens     for(i=0; i<PetscMaxThreads; i++) {
93251d315f7SKerry Stevens       ierr = pthread_mutex_init(job_tree.mutexarray[i],NULL);
93351d315f7SKerry Stevens       ierr = pthread_cond_init(job_tree.cond1array[i],NULL);
93451d315f7SKerry Stevens       ierr = pthread_cond_init(job_tree.cond2array[i],NULL);
93551d315f7SKerry Stevens       *(job_tree.arrThreadStarted[i])  = PETSC_FALSE;
93651d315f7SKerry Stevens       *(job_tree.arrThreadReady[i])    = PETSC_FALSE;
93751d315f7SKerry Stevens     }
93851d315f7SKerry Stevens     job_tree.pfunc = NULL;
93951d315f7SKerry Stevens     job_tree.pdata = (void**)malloc(N*sizeof(void*));
94051d315f7SKerry Stevens     job_tree.startJob = PETSC_FALSE;
94151d315f7SKerry Stevens     job_tree.eJobStat = JobInitiated;
94251d315f7SKerry Stevens     pVal = (int*)malloc(N*sizeof(int));
943*ba61063dSBarry Smith     /* allocate memory in the heap for the thread structure */
94451d315f7SKerry Stevens     PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t));
945*ba61063dSBarry Smith     /* create threads */
94651d315f7SKerry Stevens     for(i=0; i<N; i++) {
94751d315f7SKerry Stevens       pVal[i] = i;
94851d315f7SKerry Stevens       status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]);
949*ba61063dSBarry Smith       /* should check status */
95051d315f7SKerry Stevens     }
95151d315f7SKerry Stevens   }
95251d315f7SKerry Stevens   return NULL;
95351d315f7SKerry Stevens }
95451d315f7SKerry Stevens 
95551d315f7SKerry Stevens #undef __FUNCT__
95651d315f7SKerry Stevens #define __FUNCT__ "PetscThreadFinalize_Tree"
95751d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Tree() {
95851d315f7SKerry Stevens   int i,ierr;
95951d315f7SKerry Stevens   void* jstatus;
96051d315f7SKerry Stevens 
96151d315f7SKerry Stevens   PetscFunctionBegin;
96251d315f7SKerry Stevens 
96351d315f7SKerry Stevens   if(PetscUseThreadPool) {
964*ba61063dSBarry Smith     MainJob(FuncFinish,NULL,PetscMaxThreads);  /* set up job and broadcast work */
965*ba61063dSBarry Smith     /* join the threads */
96651d315f7SKerry Stevens     for(i=0; i<PetscMaxThreads; i++) {
96751d315f7SKerry Stevens       ierr = pthread_join(PetscThreadPoint[i],&jstatus);
968*ba61063dSBarry Smith       /* do error checking*/
96951d315f7SKerry Stevens     }
97051d315f7SKerry Stevens     free(PetscThreadPoint);
97151d315f7SKerry Stevens     free(arrmutex);
97251d315f7SKerry Stevens     free(arrcond1);
97351d315f7SKerry Stevens     free(arrcond2);
97451d315f7SKerry Stevens     free(arrstart);
97551d315f7SKerry Stevens     free(arrready);
97651d315f7SKerry Stevens     free(job_tree.pdata);
97751d315f7SKerry Stevens     free(pVal);
97851d315f7SKerry Stevens   }
97951d315f7SKerry Stevens   else {
98051d315f7SKerry Stevens   }
98151d315f7SKerry Stevens   PetscFunctionReturn(0);
98251d315f7SKerry Stevens }
98351d315f7SKerry Stevens 
98451d315f7SKerry Stevens #undef __FUNCT__
98551d315f7SKerry Stevens #define __FUNCT__ "MainWait_Tree"
98651d315f7SKerry Stevens void MainWait_Tree() {
98751d315f7SKerry Stevens   int ierr;
98851d315f7SKerry Stevens   ierr = pthread_mutex_lock(job_tree.mutexarray[0]);
98951d315f7SKerry Stevens   while(job_tree.eJobStat<JobCompleted||job_tree.startJob==PETSC_TRUE) {
99051d315f7SKerry Stevens     ierr = pthread_cond_wait(&main_cond,job_tree.mutexarray[0]);
99151d315f7SKerry Stevens   }
99251d315f7SKerry Stevens   ierr = pthread_mutex_unlock(job_tree.mutexarray[0]);
99351d315f7SKerry Stevens }
99451d315f7SKerry Stevens 
99551d315f7SKerry Stevens #undef __FUNCT__
99651d315f7SKerry Stevens #define __FUNCT__ "MainJob_Tree"
99751d315f7SKerry Stevens PetscErrorCode MainJob_Tree(void* (*pFunc)(void*),void** data,PetscInt n) {
99851d315f7SKerry Stevens   int i,ierr;
99951d315f7SKerry Stevens   PetscErrorCode ijoberr = 0;
100051d315f7SKerry Stevens   if(PetscUseThreadPool) {
100151d315f7SKerry Stevens     MainWait();
100251d315f7SKerry Stevens     job_tree.pfunc = pFunc;
100351d315f7SKerry Stevens     job_tree.pdata = data;
100451d315f7SKerry Stevens     job_tree.startJob = PETSC_TRUE;
100551d315f7SKerry Stevens     for(i=0; i<PetscMaxThreads; i++) {
100651d315f7SKerry Stevens       *(job_tree.arrThreadStarted[i]) = PETSC_FALSE;
100751d315f7SKerry Stevens     }
100851d315f7SKerry Stevens     job_tree.eJobStat = JobInitiated;
100951d315f7SKerry Stevens     ierr = pthread_cond_signal(job_tree.cond2array[0]);
101051d315f7SKerry Stevens     if(pFunc!=FuncFinish) {
1011*ba61063dSBarry Smith       MainWait(); /* why wait after? guarantees that job gets done before proceeding with result collection (if any) */
101251d315f7SKerry Stevens     }
101351d315f7SKerry Stevens   }
101451d315f7SKerry Stevens   else {
101551d315f7SKerry Stevens     pthread_t* apThread = (pthread_t*)malloc(n*sizeof(pthread_t));
101651d315f7SKerry Stevens     PetscThreadRun(MPI_COMM_WORLD,pFunc,n,apThread,data);
1017*ba61063dSBarry Smith     PetscThreadStop(MPI_COMM_WORLD,n,apThread); /* ensures that all threads are finished with the job */
101851d315f7SKerry Stevens     free(apThread);
101951d315f7SKerry Stevens   }
102051d315f7SKerry Stevens   if(ithreaderr) {
102151d315f7SKerry Stevens     ijoberr = ithreaderr;
102251d315f7SKerry Stevens   }
102351d315f7SKerry Stevens   return ijoberr;
102451d315f7SKerry Stevens }
102551d315f7SKerry Stevens /****  ****/
102651d315f7SKerry Stevens 
102751d315f7SKerry Stevens /**** 'Main' Thread Pool Functions ****/
102851d315f7SKerry Stevens void* PetscThreadFunc_Main(void* arg) {
102951d315f7SKerry Stevens   PetscErrorCode iterr;
103051d315f7SKerry Stevens   int icorr,ierr;
103151d315f7SKerry Stevens   int* pId = (int*)arg;
103251d315f7SKerry Stevens   int ThreadId = *pId;
103351d315f7SKerry Stevens   cpu_set_t mset;
103451d315f7SKerry Stevens 
103551d315f7SKerry Stevens   icorr = ThreadCoreAffinity[ThreadId];
103651d315f7SKerry Stevens   CPU_ZERO(&mset);
103751d315f7SKerry Stevens   CPU_SET(icorr,&mset);
103851d315f7SKerry Stevens   sched_setaffinity(0,sizeof(cpu_set_t),&mset);
103951d315f7SKerry Stevens 
104051d315f7SKerry Stevens   ierr = pthread_mutex_lock(job_main.mutexarray[ThreadId]);
1041*ba61063dSBarry Smith   /* update your ready status */
104251d315f7SKerry Stevens   *(job_main.arrThreadReady[ThreadId]) = PETSC_TRUE;
1043*ba61063dSBarry Smith   /* tell the BOSS that you're ready to work before you go to sleep */
104451d315f7SKerry Stevens   ierr = pthread_cond_signal(job_main.cond1array[ThreadId]);
104551d315f7SKerry Stevens 
1046*ba61063dSBarry Smith   /* the while loop needs to have an exit
1047*ba61063dSBarry Smith      the 'main' thread can terminate all the threads by performing a broadcast
1048*ba61063dSBarry Smith      and calling FuncFinish */
104951d315f7SKerry Stevens   while(PetscThreadGo) {
1050*ba61063dSBarry Smith     /* need to check the condition to ensure we don't have to wait
1051*ba61063dSBarry Smith        waiting when you don't have to causes problems
1052*ba61063dSBarry Smith      also need to check the condition to ensure proper handling of spurious wakeups */
105351d315f7SKerry Stevens     while(*(job_main.arrThreadReady[ThreadId])==PETSC_TRUE) {
1054*ba61063dSBarry Smith       /* upon entry, atomically releases the lock and blocks
1055*ba61063dSBarry Smith        upon return, has the lock */
105651d315f7SKerry Stevens         ierr = pthread_cond_wait(job_main.cond2array[ThreadId],job_main.mutexarray[ThreadId]);
1057*ba61063dSBarry Smith 	/* (job_main.arrThreadReady[ThreadId])   = PETSC_FALSE; */
105851d315f7SKerry Stevens     }
105951d315f7SKerry Stevens     ierr = pthread_mutex_unlock(job_main.mutexarray[ThreadId]);
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) {
1070*ba61063dSBarry Smith       /* reset job, get ready for more */
107151d315f7SKerry Stevens       ierr = pthread_mutex_lock(job_main.mutexarray[ThreadId]);
107251d315f7SKerry Stevens       *(job_main.arrThreadReady[ThreadId]) = PETSC_TRUE;
1073*ba61063dSBarry Smith       /* 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*));
1098*ba61063dSBarry Smith     /* 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));
1114*ba61063dSBarry Smith     /* allocate memory in the heap for the thread structure */
111551d315f7SKerry Stevens     PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t));
1116*ba61063dSBarry Smith     /* 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]);
1120*ba61063dSBarry Smith       /* 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) {
1137*ba61063dSBarry Smith     MainJob(FuncFinish,NULL,PetscMaxThreads);  /* set up job and broadcast work */
1138*ba61063dSBarry Smith     /* join the threads */
113951d315f7SKerry Stevens     for(i=0; i<PetscMaxThreads; i++) {
1140*ba61063dSBarry Smith       ierr = pthread_join(PetscThreadPoint[i],&jstatus);CHKERRQ(ierr);
114151d315f7SKerry Stevens     }
114251d315f7SKerry Stevens     free(PetscThreadPoint);
114351d315f7SKerry Stevens     free(arrmutex);
114451d315f7SKerry Stevens     free(arrcond1);
114551d315f7SKerry Stevens     free(arrcond2);
114651d315f7SKerry Stevens     free(arrstart);
114751d315f7SKerry Stevens     free(arrready);
114851d315f7SKerry Stevens     free(job_main.pdata);
114951d315f7SKerry Stevens     free(pVal);
115051d315f7SKerry Stevens   }
115151d315f7SKerry Stevens   PetscFunctionReturn(0);
115251d315f7SKerry Stevens }
115351d315f7SKerry Stevens 
115451d315f7SKerry Stevens #undef __FUNCT__
115551d315f7SKerry Stevens #define __FUNCT__ "MainWait_Main"
115651d315f7SKerry Stevens void MainWait_Main() {
115751d315f7SKerry Stevens   int i,ierr;
115851d315f7SKerry Stevens   for(i=0; i<PetscMaxThreads; i++) {
115951d315f7SKerry Stevens     ierr = pthread_mutex_lock(job_main.mutexarray[i]);
116051d315f7SKerry Stevens     while(*(job_main.arrThreadReady[i])==PETSC_FALSE) {
116151d315f7SKerry Stevens       ierr = pthread_cond_wait(job_main.cond1array[i],job_main.mutexarray[i]);
116251d315f7SKerry Stevens     }
116351d315f7SKerry Stevens     ierr = pthread_mutex_unlock(job_main.mutexarray[i]);
116451d315f7SKerry Stevens   }
116551d315f7SKerry Stevens }
116651d315f7SKerry Stevens 
116751d315f7SKerry Stevens #undef __FUNCT__
116851d315f7SKerry Stevens #define __FUNCT__ "MainJob_Main"
116951d315f7SKerry Stevens PetscErrorCode MainJob_Main(void* (*pFunc)(void*),void** data,PetscInt n) {
117051d315f7SKerry Stevens   int i,ierr;
117151d315f7SKerry Stevens   PetscErrorCode ijoberr = 0;
117251d315f7SKerry Stevens   if(PetscUseThreadPool) {
1173*ba61063dSBarry Smith     MainWait(); /* you know everyone is waiting to be signalled! */
117451d315f7SKerry Stevens     job_main.pfunc = pFunc;
117551d315f7SKerry Stevens     job_main.pdata = data;
117651d315f7SKerry Stevens     for(i=0; i<PetscMaxThreads; i++) {
1177*ba61063dSBarry Smith       *(job_main.arrThreadReady[i]) = PETSC_FALSE; /* why do this?  suppose you get into MainWait first */
117851d315f7SKerry Stevens     }
1179*ba61063dSBarry Smith     /* tell the threads to go to work */
118051d315f7SKerry Stevens     for(i=0; i<PetscMaxThreads; i++) {
118151d315f7SKerry Stevens       ierr = pthread_cond_signal(job_main.cond2array[i]);
118251d315f7SKerry Stevens     }
118351d315f7SKerry Stevens     if(pFunc!=FuncFinish) {
1184*ba61063dSBarry Smith       MainWait(); /* why wait after? guarantees that job gets done before proceeding with result collection (if any) */
118551d315f7SKerry Stevens     }
118651d315f7SKerry Stevens   }
118751d315f7SKerry Stevens   else {
118851d315f7SKerry Stevens     pthread_t* apThread = (pthread_t*)malloc(n*sizeof(pthread_t));
118951d315f7SKerry Stevens     PetscThreadRun(MPI_COMM_WORLD,pFunc,n,apThread,data);
1190*ba61063dSBarry Smith     PetscThreadStop(MPI_COMM_WORLD,n,apThread); /* ensures that all threads are finished with the job */
119151d315f7SKerry Stevens     free(apThread);
119251d315f7SKerry Stevens   }
119351d315f7SKerry Stevens   if(ithreaderr) {
119451d315f7SKerry Stevens     ijoberr = ithreaderr;
119551d315f7SKerry Stevens   }
119651d315f7SKerry Stevens   return ijoberr;
119751d315f7SKerry Stevens }
119851d315f7SKerry Stevens /****  ****/
119951d315f7SKerry Stevens 
120051d315f7SKerry Stevens /**** Chain Thread Functions ****/
120151d315f7SKerry Stevens void* PetscThreadFunc_Chain(void* arg) {
120251d315f7SKerry Stevens   PetscErrorCode iterr;
120351d315f7SKerry Stevens   int icorr,ierr;
120451d315f7SKerry Stevens   int* pId = (int*)arg;
120551d315f7SKerry Stevens   int ThreadId = *pId;
120651d315f7SKerry Stevens   int SubWorker = ThreadId + 1;
120751d315f7SKerry Stevens   PetscBool PeeOn;
120851d315f7SKerry Stevens   cpu_set_t mset;
120951d315f7SKerry Stevens 
121051d315f7SKerry Stevens   icorr = ThreadCoreAffinity[ThreadId];
121151d315f7SKerry Stevens   CPU_ZERO(&mset);
121251d315f7SKerry Stevens   CPU_SET(icorr,&mset);
121351d315f7SKerry Stevens   sched_setaffinity(0,sizeof(cpu_set_t),&mset);
121451d315f7SKerry Stevens 
121551d315f7SKerry Stevens   if(ThreadId==(PetscMaxThreads-1)) {
121651d315f7SKerry Stevens     PeeOn = PETSC_TRUE;
121751d315f7SKerry Stevens   }
121851d315f7SKerry Stevens   else {
121951d315f7SKerry Stevens     PeeOn = PETSC_FALSE;
122051d315f7SKerry Stevens   }
122151d315f7SKerry Stevens   if(PeeOn==PETSC_FALSE) {
1222*ba61063dSBarry Smith     /* check your subordinate, wait for him to be ready */
122351d315f7SKerry Stevens     ierr = pthread_mutex_lock(job_chain.mutexarray[SubWorker]);
122451d315f7SKerry Stevens     while(*(job_chain.arrThreadReady[SubWorker])==PETSC_FALSE) {
1225*ba61063dSBarry Smith       /* upon entry, automically releases the lock and blocks
1226*ba61063dSBarry Smith        upon return, has the lock */
122751d315f7SKerry Stevens       ierr = pthread_cond_wait(job_chain.cond1array[SubWorker],job_chain.mutexarray[SubWorker]);
122851d315f7SKerry Stevens     }
122951d315f7SKerry Stevens     ierr = pthread_mutex_unlock(job_chain.mutexarray[SubWorker]);
1230*ba61063dSBarry Smith     /* your subordinate is now ready*/
123151d315f7SKerry Stevens   }
123251d315f7SKerry Stevens   ierr = pthread_mutex_lock(job_chain.mutexarray[ThreadId]);
1233*ba61063dSBarry Smith   /* update your ready status */
123451d315f7SKerry Stevens   *(job_chain.arrThreadReady[ThreadId]) = PETSC_TRUE;
123551d315f7SKerry Stevens   if(ThreadId==0) {
123651d315f7SKerry Stevens     job_chain.eJobStat = JobCompleted;
1237*ba61063dSBarry Smith     /* signal main */
123851d315f7SKerry Stevens     ierr = pthread_cond_signal(&main_cond);
123951d315f7SKerry Stevens   }
124051d315f7SKerry Stevens   else {
1241*ba61063dSBarry Smith     /* tell your boss that you're ready to work */
124251d315f7SKerry Stevens     ierr = pthread_cond_signal(job_chain.cond1array[ThreadId]);
124351d315f7SKerry Stevens   }
1244*ba61063dSBarry Smith   /*  the while loop needs to have an exit
1245*ba61063dSBarry Smith      the 'main' thread can terminate all the threads by performing a broadcast
1246*ba61063dSBarry Smith    and calling FuncFinish */
124751d315f7SKerry Stevens   while(PetscThreadGo) {
1248*ba61063dSBarry Smith     /* need to check the condition to ensure we don't have to wait
1249*ba61063dSBarry Smith        waiting when you don't have to causes problems
1250*ba61063dSBarry Smith      also need to check the condition to ensure proper handling of spurious wakeups */
125151d315f7SKerry Stevens     while(*(job_chain.arrThreadReady[ThreadId])==PETSC_TRUE) {
1252*ba61063dSBarry Smith       /*upon entry, automically releases the lock and blocks
1253*ba61063dSBarry Smith        upon return, has the lock */
125451d315f7SKerry Stevens         ierr = pthread_cond_wait(job_chain.cond2array[ThreadId],job_chain.mutexarray[ThreadId]);
125551d315f7SKerry Stevens 	*(job_chain.arrThreadStarted[ThreadId]) = PETSC_TRUE;
125651d315f7SKerry Stevens 	*(job_chain.arrThreadReady[ThreadId])   = PETSC_FALSE;
125751d315f7SKerry Stevens     }
125851d315f7SKerry Stevens     if(ThreadId==0) {
125951d315f7SKerry Stevens       job_chain.startJob = PETSC_FALSE;
126051d315f7SKerry Stevens       job_chain.eJobStat = ThreadsWorking;
126151d315f7SKerry Stevens     }
126251d315f7SKerry Stevens     ierr = pthread_mutex_unlock(job_chain.mutexarray[ThreadId]);
126351d315f7SKerry Stevens     if(PeeOn==PETSC_FALSE) {
1264*ba61063dSBarry Smith       /* tell your subworker it's time to get to work */
126551d315f7SKerry Stevens       ierr = pthread_cond_signal(job_chain.cond2array[SubWorker]);
126651d315f7SKerry Stevens     }
1267*ba61063dSBarry Smith     /* do your job */
126851d315f7SKerry Stevens     if(job_chain.pdata==NULL) {
126951d315f7SKerry Stevens       iterr = (PetscErrorCode)(long int)job_chain.pfunc(job_chain.pdata);
127051d315f7SKerry Stevens     }
127151d315f7SKerry Stevens     else {
127251d315f7SKerry Stevens       iterr = (PetscErrorCode)(long int)job_chain.pfunc(job_chain.pdata[ThreadId]);
127351d315f7SKerry Stevens     }
127451d315f7SKerry Stevens     if(iterr!=0) {
127551d315f7SKerry Stevens       ithreaderr = 1;
127651d315f7SKerry Stevens     }
127751d315f7SKerry Stevens     if(PetscThreadGo) {
1278*ba61063dSBarry Smith       /* reset job, get ready for more */
127951d315f7SKerry Stevens       if(PeeOn==PETSC_FALSE) {
1280*ba61063dSBarry Smith         /* check your subordinate, wait for him to be ready
1281*ba61063dSBarry Smith          how do you know for a fact that your subordinate has actually started? */
128251d315f7SKerry Stevens         ierr = pthread_mutex_lock(job_chain.mutexarray[SubWorker]);
128351d315f7SKerry Stevens         while(*(job_chain.arrThreadReady[SubWorker])==PETSC_FALSE||*(job_chain.arrThreadStarted[SubWorker])==PETSC_FALSE) {
1284*ba61063dSBarry Smith           /* upon entry, automically releases the lock and blocks
1285*ba61063dSBarry Smith            upon return, has the lock */
128651d315f7SKerry Stevens           ierr = pthread_cond_wait(job_chain.cond1array[SubWorker],job_chain.mutexarray[SubWorker]);
128751d315f7SKerry Stevens         }
128851d315f7SKerry Stevens         ierr = pthread_mutex_unlock(job_chain.mutexarray[SubWorker]);
1289*ba61063dSBarry Smith         /* your subordinate is now ready */
129051d315f7SKerry Stevens       }
129151d315f7SKerry Stevens       ierr = pthread_mutex_lock(job_chain.mutexarray[ThreadId]);
129251d315f7SKerry Stevens       *(job_chain.arrThreadReady[ThreadId]) = PETSC_TRUE;
129351d315f7SKerry Stevens       if(ThreadId==0) {
1294*ba61063dSBarry Smith 	job_chain.eJobStat = JobCompleted; /* foreman: last thread to complete, guaranteed! */
1295*ba61063dSBarry Smith         /* root thread (foreman) signals 'main' */
129651d315f7SKerry Stevens         ierr = pthread_cond_signal(&main_cond);
129751d315f7SKerry Stevens       }
129851d315f7SKerry Stevens       else {
1299*ba61063dSBarry Smith         /* signal your boss before you go to sleep */
130051d315f7SKerry Stevens         ierr = pthread_cond_signal(job_chain.cond1array[ThreadId]);
130151d315f7SKerry Stevens       }
130251d315f7SKerry Stevens     }
130351d315f7SKerry Stevens   }
130451d315f7SKerry Stevens   return NULL;
130551d315f7SKerry Stevens }
130651d315f7SKerry Stevens 
130751d315f7SKerry Stevens #undef __FUNCT__
130851d315f7SKerry Stevens #define __FUNCT__ "PetscThreadInitialize_Chain"
130951d315f7SKerry Stevens void* PetscThreadInitialize_Chain(PetscInt N) {
131051d315f7SKerry Stevens   PetscInt i,ierr;
131151d315f7SKerry Stevens   int status;
131251d315f7SKerry Stevens 
131351d315f7SKerry Stevens   if(PetscUseThreadPool) {
131451d315f7SKerry Stevens     size_t Val1 = (size_t)CACHE_LINE_SIZE;
131551d315f7SKerry Stevens     size_t Val2 = (size_t)PetscMaxThreads*CACHE_LINE_SIZE;
131651d315f7SKerry Stevens     arrmutex = (char*)memalign(Val1,Val2);
131751d315f7SKerry Stevens     arrcond1 = (char*)memalign(Val1,Val2);
131851d315f7SKerry Stevens     arrcond2 = (char*)memalign(Val1,Val2);
131951d315f7SKerry Stevens     arrstart = (char*)memalign(Val1,Val2);
132051d315f7SKerry Stevens     arrready = (char*)memalign(Val1,Val2);
132151d315f7SKerry Stevens     job_chain.mutexarray       = (pthread_mutex_t**)malloc(PetscMaxThreads*sizeof(pthread_mutex_t*));
132251d315f7SKerry Stevens     job_chain.cond1array       = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*));
132351d315f7SKerry Stevens     job_chain.cond2array       = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*));
132451d315f7SKerry Stevens     job_chain.arrThreadStarted = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*));
132551d315f7SKerry Stevens     job_chain.arrThreadReady   = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*));
1326*ba61063dSBarry Smith     /* initialize job structure */
132751d315f7SKerry Stevens     for(i=0; i<PetscMaxThreads; i++) {
132851d315f7SKerry Stevens       job_chain.mutexarray[i]        = (pthread_mutex_t*)(arrmutex+CACHE_LINE_SIZE*i);
132951d315f7SKerry Stevens       job_chain.cond1array[i]        = (pthread_cond_t*)(arrcond1+CACHE_LINE_SIZE*i);
133051d315f7SKerry Stevens       job_chain.cond2array[i]        = (pthread_cond_t*)(arrcond2+CACHE_LINE_SIZE*i);
133151d315f7SKerry Stevens       job_chain.arrThreadStarted[i]  = (PetscBool*)(arrstart+CACHE_LINE_SIZE*i);
133251d315f7SKerry Stevens       job_chain.arrThreadReady[i]    = (PetscBool*)(arrready+CACHE_LINE_SIZE*i);
133351d315f7SKerry Stevens     }
133451d315f7SKerry Stevens     for(i=0; i<PetscMaxThreads; i++) {
133551d315f7SKerry Stevens       ierr = pthread_mutex_init(job_chain.mutexarray[i],NULL);
133651d315f7SKerry Stevens       ierr = pthread_cond_init(job_chain.cond1array[i],NULL);
133751d315f7SKerry Stevens       ierr = pthread_cond_init(job_chain.cond2array[i],NULL);
133851d315f7SKerry Stevens       *(job_chain.arrThreadStarted[i])  = PETSC_FALSE;
133951d315f7SKerry Stevens       *(job_chain.arrThreadReady[i])    = PETSC_FALSE;
134051d315f7SKerry Stevens     }
134151d315f7SKerry Stevens     job_chain.pfunc = NULL;
134251d315f7SKerry Stevens     job_chain.pdata = (void**)malloc(N*sizeof(void*));
134351d315f7SKerry Stevens     job_chain.startJob = PETSC_FALSE;
134451d315f7SKerry Stevens     job_chain.eJobStat = JobInitiated;
134551d315f7SKerry Stevens     pVal = (int*)malloc(N*sizeof(int));
1346*ba61063dSBarry Smith     /* allocate memory in the heap for the thread structure */
134751d315f7SKerry Stevens     PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t));
1348*ba61063dSBarry Smith     /* create threads */
134951d315f7SKerry Stevens     for(i=0; i<N; i++) {
135051d315f7SKerry Stevens       pVal[i] = i;
135151d315f7SKerry Stevens       status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]);
1352*ba61063dSBarry Smith       /* should check error */
135351d315f7SKerry Stevens     }
135451d315f7SKerry Stevens   }
135551d315f7SKerry Stevens   else {
135651d315f7SKerry Stevens   }
135751d315f7SKerry Stevens   return NULL;
135851d315f7SKerry Stevens }
135951d315f7SKerry Stevens 
136051d315f7SKerry Stevens 
136151d315f7SKerry Stevens #undef __FUNCT__
136251d315f7SKerry Stevens #define __FUNCT__ "PetscThreadFinalize_Chain"
136351d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_Chain() {
136451d315f7SKerry Stevens   int i,ierr;
136551d315f7SKerry Stevens   void* jstatus;
136651d315f7SKerry Stevens 
136751d315f7SKerry Stevens   PetscFunctionBegin;
136851d315f7SKerry Stevens 
136951d315f7SKerry Stevens   if(PetscUseThreadPool) {
1370*ba61063dSBarry Smith     MainJob(FuncFinish,NULL,PetscMaxThreads);  /* set up job and broadcast work */
1371*ba61063dSBarry Smith     /* join the threads */
137251d315f7SKerry Stevens     for(i=0; i<PetscMaxThreads; i++) {
137351d315f7SKerry Stevens       ierr = pthread_join(PetscThreadPoint[i],&jstatus);
1374*ba61063dSBarry Smith       /* should check error */
137551d315f7SKerry Stevens     }
137651d315f7SKerry Stevens     free(PetscThreadPoint);
137751d315f7SKerry Stevens     free(arrmutex);
137851d315f7SKerry Stevens     free(arrcond1);
137951d315f7SKerry Stevens     free(arrcond2);
138051d315f7SKerry Stevens     free(arrstart);
138151d315f7SKerry Stevens     free(arrready);
138251d315f7SKerry Stevens     free(job_chain.pdata);
138351d315f7SKerry Stevens     free(pVal);
138451d315f7SKerry Stevens   }
138551d315f7SKerry Stevens   else {
138651d315f7SKerry Stevens   }
138751d315f7SKerry Stevens   PetscFunctionReturn(0);
138851d315f7SKerry Stevens }
138951d315f7SKerry Stevens 
139051d315f7SKerry Stevens #undef __FUNCT__
139151d315f7SKerry Stevens #define __FUNCT__ "MainWait_Chain"
139251d315f7SKerry Stevens void MainWait_Chain() {
139351d315f7SKerry Stevens   int ierr;
139451d315f7SKerry Stevens   ierr = pthread_mutex_lock(job_chain.mutexarray[0]);
139551d315f7SKerry Stevens   while(job_chain.eJobStat<JobCompleted||job_chain.startJob==PETSC_TRUE) {
139651d315f7SKerry Stevens     ierr = pthread_cond_wait(&main_cond,job_chain.mutexarray[0]);
139751d315f7SKerry Stevens   }
139851d315f7SKerry Stevens   ierr = pthread_mutex_unlock(job_chain.mutexarray[0]);
139951d315f7SKerry Stevens }
140051d315f7SKerry Stevens 
140151d315f7SKerry Stevens #undef __FUNCT__
140251d315f7SKerry Stevens #define __FUNCT__ "MainJob_Chain"
140351d315f7SKerry Stevens PetscErrorCode MainJob_Chain(void* (*pFunc)(void*),void** data,PetscInt n) {
140451d315f7SKerry Stevens   int i,ierr;
140551d315f7SKerry Stevens   PetscErrorCode ijoberr = 0;
140651d315f7SKerry Stevens   if(PetscUseThreadPool) {
140751d315f7SKerry Stevens     MainWait();
140851d315f7SKerry Stevens     job_chain.pfunc = pFunc;
140951d315f7SKerry Stevens     job_chain.pdata = data;
141051d315f7SKerry Stevens     job_chain.startJob = PETSC_TRUE;
141151d315f7SKerry Stevens     for(i=0; i<PetscMaxThreads; i++) {
141251d315f7SKerry Stevens       *(job_chain.arrThreadStarted[i]) = PETSC_FALSE;
141351d315f7SKerry Stevens     }
141451d315f7SKerry Stevens     job_chain.eJobStat = JobInitiated;
141551d315f7SKerry Stevens     ierr = pthread_cond_signal(job_chain.cond2array[0]);
141651d315f7SKerry Stevens     if(pFunc!=FuncFinish) {
1417*ba61063dSBarry Smith       MainWait(); /* why wait after? guarantees that job gets done before proceeding with result collection (if any) */
141851d315f7SKerry Stevens     }
141951d315f7SKerry Stevens   }
142051d315f7SKerry Stevens   else {
142151d315f7SKerry Stevens     pthread_t* apThread = (pthread_t*)malloc(n*sizeof(pthread_t));
142251d315f7SKerry Stevens     PetscThreadRun(MPI_COMM_WORLD,pFunc,n,apThread,data);
1423*ba61063dSBarry Smith     PetscThreadStop(MPI_COMM_WORLD,n,apThread); /* ensures that all threads are finished with the job */
142451d315f7SKerry Stevens     free(apThread);
142551d315f7SKerry Stevens   }
142651d315f7SKerry Stevens   if(ithreaderr) {
142751d315f7SKerry Stevens     ijoberr = ithreaderr;
142851d315f7SKerry Stevens   }
142951d315f7SKerry Stevens   return ijoberr;
143051d315f7SKerry Stevens }
143151d315f7SKerry Stevens /****  ****/
143251d315f7SKerry Stevens 
1433*ba61063dSBarry Smith #if defined(PETSC_HAVE_PTHREAD_BARRIER)
143451d315f7SKerry Stevens /**** True Thread Functions ****/
143551d315f7SKerry Stevens void* PetscThreadFunc_True(void* arg) {
143651d315f7SKerry Stevens   int icorr,ierr,iVal;
143751dcc849SKerry Stevens   int* pId = (int*)arg;
143851dcc849SKerry Stevens   int ThreadId = *pId;
14390ca81413SKerry Stevens   PetscErrorCode iterr;
144051d315f7SKerry Stevens   cpu_set_t mset;
144151dcc849SKerry Stevens 
144251d315f7SKerry Stevens   icorr = ThreadCoreAffinity[ThreadId];
144351d315f7SKerry Stevens   CPU_ZERO(&mset);
144451d315f7SKerry Stevens   CPU_SET(icorr,&mset);
144551d315f7SKerry Stevens   sched_setaffinity(0,sizeof(cpu_set_t),&mset);
144651d315f7SKerry Stevens 
144751d315f7SKerry Stevens   ierr = pthread_mutex_lock(&job_true.mutex);
144851d315f7SKerry Stevens   job_true.iNumReadyThreads++;
144951d315f7SKerry Stevens   if(job_true.iNumReadyThreads==PetscMaxThreads) {
145051dcc849SKerry Stevens     ierr = pthread_cond_signal(&main_cond);
145151dcc849SKerry Stevens   }
1452*ba61063dSBarry Smith   /*the while loop needs to have an exit
1453*ba61063dSBarry Smith     the 'main' thread can terminate all the threads by performing a broadcast
1454*ba61063dSBarry Smith    and calling FuncFinish */
145551dcc849SKerry Stevens   while(PetscThreadGo) {
1456*ba61063dSBarry Smith     /*need to check the condition to ensure we don't have to wait
1457*ba61063dSBarry Smith       waiting when you don't have to causes problems
1458*ba61063dSBarry Smith      also need to wait if another thread sneaks in and messes with the predicate */
145951d315f7SKerry Stevens     while(job_true.startJob==PETSC_FALSE&&job_true.iNumJobThreads==0) {
1460*ba61063dSBarry Smith       /* upon entry, automically releases the lock and blocks
1461*ba61063dSBarry Smith        upon return, has the lock */
146251d315f7SKerry Stevens       ierr = pthread_cond_wait(&job_true.cond,&job_true.mutex);
146351dcc849SKerry Stevens     }
146451d315f7SKerry Stevens     job_true.startJob = PETSC_FALSE;
146551d315f7SKerry Stevens     job_true.iNumJobThreads--;
146651d315f7SKerry Stevens     job_true.iNumReadyThreads--;
146751d315f7SKerry Stevens     iVal = PetscMaxThreads-job_true.iNumReadyThreads-1;
146851d315f7SKerry Stevens     pthread_mutex_unlock(&job_true.mutex);
146951d315f7SKerry Stevens     if(job_true.pdata==NULL) {
147051d315f7SKerry Stevens       iterr = (PetscErrorCode)(long int)job_true.pfunc(job_true.pdata);
147151dcc849SKerry Stevens     }
147251dcc849SKerry Stevens     else {
147351d315f7SKerry Stevens       iterr = (PetscErrorCode)(long int)job_true.pfunc(job_true.pdata[iVal]);
147451dcc849SKerry Stevens     }
14750ca81413SKerry Stevens     if(iterr!=0) {
14760ca81413SKerry Stevens       ithreaderr = 1;
14770ca81413SKerry Stevens     }
1478*ba61063dSBarry Smith     /* the barrier is necessary BECAUSE: look at job_true.iNumReadyThreads
1479*ba61063dSBarry Smith       what happens if a thread finishes before they all start? BAD!
1480*ba61063dSBarry Smith      what happens if a thread finishes before any else start? BAD! */
1481*ba61063dSBarry Smith     pthread_barrier_wait(job_true.pbarr); /* ensures all threads are finished */
1482*ba61063dSBarry Smith     /* reset job */
148351dcc849SKerry Stevens     if(PetscThreadGo) {
148451d315f7SKerry Stevens       pthread_mutex_lock(&job_true.mutex);
148551d315f7SKerry Stevens       job_true.iNumReadyThreads++;
148651d315f7SKerry Stevens       if(job_true.iNumReadyThreads==PetscMaxThreads) {
1487*ba61063dSBarry Smith 	/* signal the 'main' thread that the job is done! (only done once) */
148851dcc849SKerry Stevens 	ierr = pthread_cond_signal(&main_cond);
148951dcc849SKerry Stevens       }
149051dcc849SKerry Stevens     }
149151dcc849SKerry Stevens   }
149251dcc849SKerry Stevens   return NULL;
149351dcc849SKerry Stevens }
149451dcc849SKerry Stevens 
1495f09cb4aaSKerry Stevens #undef __FUNCT__
149651d315f7SKerry Stevens #define __FUNCT__ "PetscThreadInitialize_True"
149751d315f7SKerry Stevens void* PetscThreadInitialize_True(PetscInt N) {
149851dcc849SKerry Stevens   PetscInt i;
149951dcc849SKerry Stevens   int status;
15000ca81413SKerry Stevens 
15010ca81413SKerry Stevens   if(PetscUseThreadPool) {
1502f09cb4aaSKerry Stevens     pVal = (int*)malloc(N*sizeof(int));
1503*ba61063dSBarry Smith     /* allocate memory in the heap for the thread structure */
150451dcc849SKerry Stevens     PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t));
1505*ba61063dSBarry Smith     BarrPoint = (pthread_barrier_t*)malloc((N+1)*sizeof(pthread_barrier_t)); /* BarrPoint[0] makes no sense, don't use it! */
150651d315f7SKerry Stevens     job_true.pdata = (void**)malloc(N*sizeof(void*));
150751dcc849SKerry Stevens     for(i=0; i<N; i++) {
1508f09cb4aaSKerry Stevens       pVal[i] = i;
1509f09cb4aaSKerry Stevens       status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]);
1510*ba61063dSBarry Smith       /* error check to ensure proper thread creation */
151151dcc849SKerry Stevens       status = pthread_barrier_init(&BarrPoint[i+1],NULL,i+1);
1512*ba61063dSBarry Smith       /* should check error */
151351dcc849SKerry Stevens     }
15140ca81413SKerry Stevens   }
15150ca81413SKerry Stevens   else {
15160ca81413SKerry Stevens   }
151751dcc849SKerry Stevens   return NULL;
151851dcc849SKerry Stevens }
151951dcc849SKerry Stevens 
1520f09cb4aaSKerry Stevens 
1521f09cb4aaSKerry Stevens #undef __FUNCT__
152251d315f7SKerry Stevens #define __FUNCT__ "PetscThreadFinalize_True"
152351d315f7SKerry Stevens PetscErrorCode PetscThreadFinalize_True() {
152451dcc849SKerry Stevens   int i,ierr;
152551dcc849SKerry Stevens   void* jstatus;
152651dcc849SKerry Stevens 
152751dcc849SKerry Stevens   PetscFunctionBegin;
15280ca81413SKerry Stevens 
15290ca81413SKerry Stevens   if(PetscUseThreadPool) {
1530*ba61063dSBarry Smith     MainJob(FuncFinish,NULL,PetscMaxThreads);  /* set up job and broadcast work */
1531*ba61063dSBarry Smith     /* join the threads */
153251dcc849SKerry Stevens     for(i=0; i<PetscMaxThreads; i++) {
153351dcc849SKerry Stevens       ierr = pthread_join(PetscThreadPoint[i],&jstatus);
1534*ba61063dSBarry Smith       /* should check error */
153551dcc849SKerry Stevens     }
153651dcc849SKerry Stevens     free(BarrPoint);
153751dcc849SKerry Stevens     free(PetscThreadPoint);
15380ca81413SKerry Stevens   }
15390ca81413SKerry Stevens   else {
15400ca81413SKerry Stevens   }
154151dcc849SKerry Stevens   PetscFunctionReturn(0);
154251dcc849SKerry Stevens }
154351dcc849SKerry Stevens 
1544f09cb4aaSKerry Stevens #undef __FUNCT__
154551d315f7SKerry Stevens #define __FUNCT__ "MainWait_True"
154651d315f7SKerry Stevens void MainWait_True() {
154751dcc849SKerry Stevens   int ierr;
154851d315f7SKerry Stevens   while(job_true.iNumReadyThreads<PetscMaxThreads||job_true.startJob==PETSC_TRUE) {
154951d315f7SKerry Stevens     ierr = pthread_cond_wait(&main_cond,&job_true.mutex);
155051dcc849SKerry Stevens   }
155151d315f7SKerry Stevens   ierr = pthread_mutex_unlock(&job_true.mutex);
155251dcc849SKerry Stevens }
155351dcc849SKerry Stevens 
1554f09cb4aaSKerry Stevens #undef __FUNCT__
155551d315f7SKerry Stevens #define __FUNCT__ "MainJob_True"
155651d315f7SKerry Stevens PetscErrorCode MainJob_True(void* (*pFunc)(void*),void** data,PetscInt n) {
155751dcc849SKerry Stevens   int ierr;
15580ca81413SKerry Stevens   PetscErrorCode ijoberr = 0;
15590ca81413SKerry Stevens   if(PetscUseThreadPool) {
15600ca81413SKerry Stevens     MainWait();
156151d315f7SKerry Stevens     job_true.pfunc = pFunc;
156251d315f7SKerry Stevens     job_true.pdata = data;
156351d315f7SKerry Stevens     job_true.pbarr = &BarrPoint[n];
156451d315f7SKerry Stevens     job_true.iNumJobThreads = n;
156551d315f7SKerry Stevens     job_true.startJob = PETSC_TRUE;
156651d315f7SKerry Stevens     ierr = pthread_cond_broadcast(&job_true.cond);
15670ca81413SKerry Stevens     if(pFunc!=FuncFinish) {
1568*ba61063dSBarry Smith       MainWait(); /* why wait after? guarantees that job gets done */
15690ca81413SKerry Stevens     }
15700ca81413SKerry Stevens   }
15710ca81413SKerry Stevens   else {
15720ca81413SKerry Stevens     pthread_t* apThread = (pthread_t*)malloc(n*sizeof(pthread_t));
15730ca81413SKerry Stevens     PetscThreadRun(MPI_COMM_WORLD,pFunc,n,apThread,data);
1574*ba61063dSBarry Smith     PetscThreadStop(MPI_COMM_WORLD,n,apThread); /* ensures that all threads are finished with the job */
15750ca81413SKerry Stevens     free(apThread);
15760ca81413SKerry Stevens   }
15770ca81413SKerry Stevens   if(ithreaderr) {
15780ca81413SKerry Stevens     ijoberr = ithreaderr;
15790ca81413SKerry Stevens   }
15800ca81413SKerry Stevens   return ijoberr;
158151dcc849SKerry Stevens }
158251d315f7SKerry Stevens /****  ****/
1583*ba61063dSBarry Smith #endif
158451dcc849SKerry Stevens 
158551dcc849SKerry Stevens void* FuncFinish(void* arg) {
158651dcc849SKerry Stevens   PetscThreadGo = PETSC_FALSE;
15870ca81413SKerry Stevens   return(0);
158851dcc849SKerry Stevens }
1589*ba61063dSBarry Smith 
1590*ba61063dSBarry Smith #endif
1591