xref: /petsc/src/sys/objects/init.c (revision 24edbb7e7869e61eb26a18dba63dc481248fd073)
1 /*
2 
3    This file defines part of the initialization of PETSc
4 
5   This file uses regular malloc and free because it cannot know
6   what malloc is being used until it has already processed the input.
7 */
8 
9 #include <petscsys.h>        /*I  "petscsys.h"   I*/
10 
11 #ifndef _GNU_SOURCE
12 #define _GNU_SOURCE
13 #endif
14 #if defined(PETSC_HAVE_SCHED_H)
15 #ifndef __USE_GNU
16 #define __USE_GNU
17 #endif
18 #include <sched.h>
19 #endif
20 #if defined(PETSC_HAVE_PTHREAD_H)
21 #include <pthread.h>
22 #endif
23 
24 #if defined(PETSC_HAVE_SYS_SYSINFO_H)
25 #include <sys/sysinfo.h>
26 #endif
27 #if defined(PETSC_HAVE_UNISTD_H)
28 #include <unistd.h>
29 #endif
30 #if defined(PETSC_HAVE_STDLIB_H)
31 #include <stdlib.h>
32 #endif
33 #if defined(PETSC_HAVE_MALLOC_H)
34 #include <malloc.h>
35 #endif
36 #if defined(PETSC_HAVE_VALGRIND)
37 #include <valgrind/valgrind.h>
38 #endif
39 
40 /* ------------------------Nasty global variables -------------------------------*/
41 /*
42      Indicates if PETSc started up MPI, or it was
43    already started before PETSc was initialized.
44 */
45 PetscBool    PetscBeganMPI         = PETSC_FALSE;
46 PetscBool    PetscInitializeCalled = PETSC_FALSE;
47 PetscBool    PetscFinalizeCalled   = PETSC_FALSE;
48 PetscBool    PetscUseThreadPool    = PETSC_FALSE;
49 PetscBool    PetscThreadGo         = PETSC_TRUE;
50 PetscMPIInt  PetscGlobalRank = -1;
51 PetscMPIInt  PetscGlobalSize = -1;
52 
53 #if defined(PETSC_HAVE_PTHREADCLASSES)
54 PetscMPIInt  PetscMaxThreads = 2;
55 pthread_t*   PetscThreadPoint;
56 #define PETSC_HAVE_PTHREAD_BARRIER
57 #if defined(PETSC_HAVE_PTHREAD_BARRIER)
58 pthread_barrier_t* BarrPoint;   /* used by 'true' thread pool */
59 #endif
60 PetscErrorCode ithreaderr = 0;
61 int*         pVal;
62 
63 #define CACHE_LINE_SIZE 64  /* used by 'chain', 'main','tree' thread pools */
64 int* ThreadCoreAffinity;
65 
66 typedef enum {JobInitiated,ThreadsWorking,JobCompleted} estat;  /* used by 'chain','tree' thread pool */
67 
68 typedef struct {
69   pthread_mutex_t** mutexarray;
70   pthread_cond_t**  cond1array;
71   pthread_cond_t** cond2array;
72   void* (*pfunc)(void*);
73   void** pdata;
74   PetscBool startJob;
75   estat eJobStat;
76   PetscBool** arrThreadStarted;
77   PetscBool** arrThreadReady;
78 } sjob_tree;
79 sjob_tree job_tree;
80 typedef struct {
81   pthread_mutex_t** mutexarray;
82   pthread_cond_t**  cond1array;
83   pthread_cond_t** cond2array;
84   void* (*pfunc)(void*);
85   void** pdata;
86   PetscBool** arrThreadReady;
87 } sjob_main;
88 sjob_main job_main;
89 typedef struct {
90   pthread_mutex_t** mutexarray;
91   pthread_cond_t**  cond1array;
92   pthread_cond_t** cond2array;
93   void* (*pfunc)(void*);
94   void** pdata;
95   PetscBool startJob;
96   estat eJobStat;
97   PetscBool** arrThreadStarted;
98   PetscBool** arrThreadReady;
99 } sjob_chain;
100 sjob_chain job_chain;
101 #if defined(PETSC_HAVE_PTHREAD_BARRIER)
102 typedef struct {
103   pthread_mutex_t mutex;
104   pthread_cond_t cond;
105   void* (*pfunc)(void*);
106   void** pdata;
107   pthread_barrier_t* pbarr;
108   int iNumJobThreads;
109   int iNumReadyThreads;
110   PetscBool startJob;
111 } sjob_true;
112 sjob_true job_true = {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER,NULL,NULL,NULL,0,0,PETSC_FALSE};
113 #endif
114 
115 pthread_cond_t  main_cond  = PTHREAD_COND_INITIALIZER;  /* used by 'true', 'chain','tree' thread pools */
116 char* arrmutex; /* used by 'chain','main','tree' thread pools */
117 char* arrcond1; /* used by 'chain','main','tree' thread pools */
118 char* arrcond2; /* used by 'chain','main','tree' thread pools */
119 char* arrstart; /* used by 'chain','main','tree' thread pools */
120 char* arrready; /* used by 'chain','main','tree' thread pools */
121 
122 /* Function Pointers */
123 void*          (*PetscThreadFunc)(void*) = NULL;
124 void*          (*PetscThreadInitialize)(PetscInt) = NULL;
125 PetscErrorCode (*PetscThreadFinalize)(void) = NULL;
126 void           (*MainWait)(void) = NULL;
127 PetscErrorCode (*MainJob)(void* (*pFunc)(void*),void**,PetscInt) = NULL;
128 /**** Tree Thread Pool Functions ****/
129 void*          PetscThreadFunc_Tree(void*);
130 void*          PetscThreadInitialize_Tree(PetscInt);
131 PetscErrorCode PetscThreadFinalize_Tree(void);
132 void           MainWait_Tree(void);
133 PetscErrorCode MainJob_Tree(void* (*pFunc)(void*),void**,PetscInt);
134 /**** Main Thread Pool Functions ****/
135 void*          PetscThreadFunc_Main(void*);
136 void*          PetscThreadInitialize_Main(PetscInt);
137 PetscErrorCode PetscThreadFinalize_Main(void);
138 void           MainWait_Main(void);
139 PetscErrorCode MainJob_Main(void* (*pFunc)(void*),void**,PetscInt);
140 /**** Chain Thread Pool Functions ****/
141 void*          PetscThreadFunc_Chain(void*);
142 void*          PetscThreadInitialize_Chain(PetscInt);
143 PetscErrorCode PetscThreadFinalize_Chain(void);
144 void           MainWait_Chain(void);
145 PetscErrorCode MainJob_Chain(void* (*pFunc)(void*),void**,PetscInt);
146 /**** True Thread Pool Functions ****/
147 void*          PetscThreadFunc_True(void*);
148 void*          PetscThreadInitialize_True(PetscInt);
149 PetscErrorCode PetscThreadFinalize_True(void);
150 void           MainWait_True(void);
151 PetscErrorCode MainJob_True(void* (*pFunc)(void*),void**,PetscInt);
152 /**** NO Thread Pool Function  ****/
153 PetscErrorCode MainJob_Spawn(void* (*pFunc)(void*),void**,PetscInt);
154 /****  ****/
155 void* FuncFinish(void*);
156 void* PetscThreadRun(MPI_Comm Comm,void* (*pFunc)(void*),int,pthread_t*,void**);
157 void* PetscThreadStop(MPI_Comm Comm,int,pthread_t*);
158 #endif
159 
160 #if defined(PETSC_USE_COMPLEX)
161 #if defined(PETSC_COMPLEX_INSTANTIATE)
162 template <> class std::complex<double>; /* instantiate complex template class */
163 #endif
164 #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
165 MPI_Datatype   MPIU_C_DOUBLE_COMPLEX;
166 MPI_Datatype   MPIU_C_COMPLEX;
167 #endif
168 PetscScalar    PETSC_i;
169 #else
170 PetscScalar    PETSC_i = 0.0;
171 #endif
172 #if defined(PETSC_USE_REAL___FLOAT128)
173 MPI_Datatype   MPIU___FLOAT128 = 0;
174 #endif
175 MPI_Datatype   MPIU_2SCALAR = 0;
176 MPI_Datatype   MPIU_2INT = 0;
177 
178 /*
179      These are needed by petscbt.h
180 */
181 #include <petscbt.h>
182 char      _BT_mask = ' ';
183 char      _BT_c = ' ';
184 PetscInt  _BT_idx  = 0;
185 
186 /*
187        Function that is called to display all error messages
188 */
189 PetscErrorCode  (*PetscErrorPrintf)(const char [],...)          = PetscErrorPrintfDefault;
190 PetscErrorCode  (*PetscHelpPrintf)(MPI_Comm,const char [],...)  = PetscHelpPrintfDefault;
191 #if defined(PETSC_HAVE_MATLAB_ENGINE)
192 PetscErrorCode  (*PetscVFPrintf)(FILE*,const char[],va_list)    = PetscVFPrintf_Matlab;
193 #else
194 PetscErrorCode  (*PetscVFPrintf)(FILE*,const char[],va_list)    = PetscVFPrintfDefault;
195 #endif
196 /*
197   This is needed to turn on/off cusp synchronization */
198 PetscBool   synchronizeCUSP = PETSC_FALSE;
199 
200 /* ------------------------------------------------------------------------------*/
201 /*
202    Optional file where all PETSc output from various prints is saved
203 */
204 FILE *petsc_history = PETSC_NULL;
205 
206 #undef __FUNCT__
207 #define __FUNCT__ "PetscOpenHistoryFile"
208 PetscErrorCode  PetscOpenHistoryFile(const char filename[],FILE **fd)
209 {
210   PetscErrorCode ierr;
211   PetscMPIInt    rank,size;
212   char           pfile[PETSC_MAX_PATH_LEN],pname[PETSC_MAX_PATH_LEN],fname[PETSC_MAX_PATH_LEN],date[64];
213   char           version[256];
214 
215   PetscFunctionBegin;
216   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
217   if (!rank) {
218     char        arch[10];
219     int         err;
220     PetscViewer viewer;
221 
222     ierr = PetscGetArchType(arch,10);CHKERRQ(ierr);
223     ierr = PetscGetDate(date,64);CHKERRQ(ierr);
224     ierr = PetscGetVersion(version,256);CHKERRQ(ierr);
225     ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
226     if (filename) {
227       ierr = PetscFixFilename(filename,fname);CHKERRQ(ierr);
228     } else {
229       ierr = PetscGetHomeDirectory(pfile,240);CHKERRQ(ierr);
230       ierr = PetscStrcat(pfile,"/.petschistory");CHKERRQ(ierr);
231       ierr = PetscFixFilename(pfile,fname);CHKERRQ(ierr);
232     }
233 
234     *fd = fopen(fname,"a"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file: %s",fname);
235     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr);
236     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"%s %s\n",version,date);CHKERRQ(ierr);
237     ierr = PetscGetProgramName(pname,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
238     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"%s on a %s, %d proc. with options:\n",pname,arch,size);CHKERRQ(ierr);
239     ierr = PetscViewerASCIIOpenWithFILE(PETSC_COMM_WORLD,*fd,&viewer);CHKERRQ(ierr);
240     ierr = PetscOptionsView(viewer);CHKERRQ(ierr);
241     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
242     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr);
243     err = fflush(*fd);
244     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
245   }
246   PetscFunctionReturn(0);
247 }
248 
249 #undef __FUNCT__
250 #define __FUNCT__ "PetscCloseHistoryFile"
251 PetscErrorCode  PetscCloseHistoryFile(FILE **fd)
252 {
253   PetscErrorCode ierr;
254   PetscMPIInt    rank;
255   char           date[64];
256   int            err;
257 
258   PetscFunctionBegin;
259   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
260   if (!rank) {
261     ierr = PetscGetDate(date,64);CHKERRQ(ierr);
262     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr);
263     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"Finished at %s\n",date);CHKERRQ(ierr);
264     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"---------------------------------------------------------\n");CHKERRQ(ierr);
265     err = fflush(*fd);
266     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
267     err = fclose(*fd);
268     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
269   }
270   PetscFunctionReturn(0);
271 }
272 
273 /* ------------------------------------------------------------------------------*/
274 
275 /*
276    This is ugly and probably belongs somewhere else, but I want to
277   be able to put a true MPI abort error handler with command line args.
278 
279     This is so MPI errors in the debugger will leave all the stack
280   frames. The default MP_Abort() cleans up and exits thus providing no useful information
281   in the debugger hence we call abort() instead of MPI_Abort().
282 */
283 
284 #undef __FUNCT__
285 #define __FUNCT__ "Petsc_MPI_AbortOnError"
286 void Petsc_MPI_AbortOnError(MPI_Comm *comm,PetscMPIInt *flag)
287 {
288   PetscFunctionBegin;
289   (*PetscErrorPrintf)("MPI error %d\n",*flag);
290   abort();
291 }
292 
293 #undef __FUNCT__
294 #define __FUNCT__ "Petsc_MPI_DebuggerOnError"
295 void Petsc_MPI_DebuggerOnError(MPI_Comm *comm,PetscMPIInt *flag)
296 {
297   PetscErrorCode ierr;
298 
299   PetscFunctionBegin;
300   (*PetscErrorPrintf)("MPI error %d\n",*flag);
301   ierr = PetscAttachDebugger();
302   if (ierr) { /* hopeless so get out */
303     MPI_Abort(*comm,*flag);
304   }
305 }
306 
307 #undef __FUNCT__
308 #define __FUNCT__ "PetscEnd"
309 /*@C
310    PetscEnd - Calls PetscFinalize() and then ends the program. This is useful if one
311      wishes a clean exit somewhere deep in the program.
312 
313    Collective on PETSC_COMM_WORLD
314 
315    Options Database Keys are the same as for PetscFinalize()
316 
317    Level: advanced
318 
319    Note:
320    See PetscInitialize() for more general runtime options.
321 
322 .seealso: PetscInitialize(), PetscOptionsView(), PetscMallocDump(), PetscMPIDump(), PetscFinalize()
323 @*/
324 PetscErrorCode  PetscEnd(void)
325 {
326   PetscFunctionBegin;
327   PetscFinalize();
328   exit(0);
329   return 0;
330 }
331 
332 PetscBool    PetscOptionsPublish = PETSC_FALSE;
333 extern PetscErrorCode        PetscSetUseTrMalloc_Private(void);
334 extern PetscBool  petscsetmallocvisited;
335 static char       emacsmachinename[256];
336 
337 PetscErrorCode (*PetscExternalVersionFunction)(MPI_Comm) = 0;
338 PetscErrorCode (*PetscExternalHelpFunction)(MPI_Comm)    = 0;
339 
340 #undef __FUNCT__
341 #define __FUNCT__ "PetscSetHelpVersionFunctions"
342 /*@C
343    PetscSetHelpVersionFunctions - Sets functions that print help and version information
344    before the PETSc help and version information is printed. Must call BEFORE PetscInitialize().
345    This routine enables a "higher-level" package that uses PETSc to print its messages first.
346 
347    Input Parameter:
348 +  help - the help function (may be PETSC_NULL)
349 -  version - the version function (may be PETSC_NULL)
350 
351    Level: developer
352 
353    Concepts: package help message
354 
355 @*/
356 PetscErrorCode  PetscSetHelpVersionFunctions(PetscErrorCode (*help)(MPI_Comm),PetscErrorCode (*version)(MPI_Comm))
357 {
358   PetscFunctionBegin;
359   PetscExternalHelpFunction    = help;
360   PetscExternalVersionFunction = version;
361   PetscFunctionReturn(0);
362 }
363 
364 #undef __FUNCT__
365 #define __FUNCT__ "PetscOptionsCheckInitial_Private"
366 PetscErrorCode  PetscOptionsCheckInitial_Private(void)
367 {
368   char           string[64],mname[PETSC_MAX_PATH_LEN],*f;
369   MPI_Comm       comm = PETSC_COMM_WORLD;
370   PetscBool      flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE,flg4 = PETSC_FALSE,flag,flgz,flgzout;
371   PetscErrorCode ierr;
372   PetscReal      si;
373   int            i;
374   PetscMPIInt    rank;
375   char           version[256];
376 
377   PetscFunctionBegin;
378   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
379 
380   /*
381       Setup the memory management; support for tracing malloc() usage
382   */
383   ierr = PetscOptionsHasName(PETSC_NULL,"-malloc_log",&flg3);CHKERRQ(ierr);
384 #if defined(PETSC_USE_DEBUG) && !defined(PETSC_USE_PTHREAD)
385   ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc",&flg1,&flg2);CHKERRQ(ierr);
386   if ((!flg2 || flg1) && !petscsetmallocvisited) {
387 #if defined(PETSC_HAVE_VALGRIND)
388     if (flg2 || !(RUNNING_ON_VALGRIND)) {
389       /* turn off default -malloc if valgrind is being used */
390 #endif
391       ierr = PetscSetUseTrMalloc_Private();CHKERRQ(ierr);
392 #if defined(PETSC_HAVE_VALGRIND)
393     }
394 #endif
395   }
396 #else
397   ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_dump",&flg1,PETSC_NULL);CHKERRQ(ierr);
398   ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc",&flg2,PETSC_NULL);CHKERRQ(ierr);
399   if (flg1 || flg2 || flg3) {ierr = PetscSetUseTrMalloc_Private();CHKERRQ(ierr);}
400 #endif
401   if (flg3) {
402     ierr = PetscMallocSetDumpLog();CHKERRQ(ierr);
403   }
404   flg1 = PETSC_FALSE;
405   ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_debug",&flg1,PETSC_NULL);CHKERRQ(ierr);
406   if (flg1) {
407     ierr = PetscSetUseTrMalloc_Private();CHKERRQ(ierr);
408     ierr = PetscMallocDebug(PETSC_TRUE);CHKERRQ(ierr);
409   }
410 
411   flg1 = PETSC_FALSE;
412   ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_info",&flg1,PETSC_NULL);CHKERRQ(ierr);
413   if (!flg1) {
414     flg1 = PETSC_FALSE;
415     ierr = PetscOptionsGetBool(PETSC_NULL,"-memory_info",&flg1,PETSC_NULL);CHKERRQ(ierr);
416   }
417   if (flg1) {
418     ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
419   }
420 
421   /*
422       Set the display variable for graphics
423   */
424   ierr = PetscSetDisplay();CHKERRQ(ierr);
425 
426 
427   /*
428       Print the PETSc version information
429   */
430   ierr = PetscOptionsHasName(PETSC_NULL,"-v",&flg1);CHKERRQ(ierr);
431   ierr = PetscOptionsHasName(PETSC_NULL,"-version",&flg2);CHKERRQ(ierr);
432   ierr = PetscOptionsHasName(PETSC_NULL,"-help",&flg3);CHKERRQ(ierr);
433   if (flg1 || flg2 || flg3){
434 
435     /*
436        Print "higher-level" package version message
437     */
438     if (PetscExternalVersionFunction) {
439       ierr = (*PetscExternalVersionFunction)(comm);CHKERRQ(ierr);
440     }
441 
442     ierr = PetscGetVersion(version,256);CHKERRQ(ierr);
443     ierr = (*PetscHelpPrintf)(comm,"--------------------------------------------\
444 ------------------------------\n");CHKERRQ(ierr);
445     ierr = (*PetscHelpPrintf)(comm,"%s\n",version);CHKERRQ(ierr);
446     ierr = (*PetscHelpPrintf)(comm,"%s",PETSC_AUTHOR_INFO);CHKERRQ(ierr);
447     ierr = (*PetscHelpPrintf)(comm,"See docs/changes/index.html for recent updates.\n");CHKERRQ(ierr);
448     ierr = (*PetscHelpPrintf)(comm,"See docs/faq.html for problems.\n");CHKERRQ(ierr);
449     ierr = (*PetscHelpPrintf)(comm,"See docs/manualpages/index.html for help. \n");CHKERRQ(ierr);
450     ierr = (*PetscHelpPrintf)(comm,"Libraries linked from %s\n",PETSC_LIB_DIR);CHKERRQ(ierr);
451     ierr = (*PetscHelpPrintf)(comm,"--------------------------------------------\
452 ------------------------------\n");CHKERRQ(ierr);
453   }
454 
455   /*
456        Print "higher-level" package help message
457   */
458   if (flg3){
459     if (PetscExternalHelpFunction) {
460       ierr = (*PetscExternalHelpFunction)(comm);CHKERRQ(ierr);
461     }
462   }
463 
464   /*
465       Setup the error handling
466   */
467   flg1 = PETSC_FALSE;
468   ierr = PetscOptionsGetBool(PETSC_NULL,"-on_error_abort",&flg1,PETSC_NULL);CHKERRQ(ierr);
469   if (flg1) { ierr = PetscPushErrorHandler(PetscAbortErrorHandler,0);CHKERRQ(ierr);}
470   flg1 = PETSC_FALSE;
471   ierr = PetscOptionsGetBool(PETSC_NULL,"-on_error_mpiabort",&flg1,PETSC_NULL);CHKERRQ(ierr);
472   if (flg1) { ierr = PetscPushErrorHandler(PetscMPIAbortErrorHandler,0);CHKERRQ(ierr);}
473   flg1 = PETSC_FALSE;
474   ierr = PetscOptionsGetBool(PETSC_NULL,"-mpi_return_on_error",&flg1,PETSC_NULL);CHKERRQ(ierr);
475   if (flg1) {
476     ierr = MPI_Errhandler_set(comm,MPI_ERRORS_RETURN);CHKERRQ(ierr);
477   }
478   flg1 = PETSC_FALSE;
479   ierr = PetscOptionsGetBool(PETSC_NULL,"-no_signal_handler",&flg1,PETSC_NULL);CHKERRQ(ierr);
480   if (!flg1) {ierr = PetscPushSignalHandler(PetscDefaultSignalHandler,(void*)0);CHKERRQ(ierr);}
481   flg1 = PETSC_FALSE;
482   ierr = PetscOptionsGetBool(PETSC_NULL,"-fp_trap",&flg1,PETSC_NULL);CHKERRQ(ierr);
483   if (flg1) {ierr = PetscSetFPTrap(PETSC_FP_TRAP_ON);CHKERRQ(ierr);}
484 
485   /*
486       Setup debugger information
487   */
488   ierr = PetscSetDefaultDebugger();CHKERRQ(ierr);
489   ierr = PetscOptionsGetString(PETSC_NULL,"-on_error_attach_debugger",string,64,&flg1);CHKERRQ(ierr);
490   if (flg1) {
491     MPI_Errhandler err_handler;
492 
493     ierr = PetscSetDebuggerFromString(string);CHKERRQ(ierr);
494     ierr = MPI_Errhandler_create((MPI_Handler_function*)Petsc_MPI_DebuggerOnError,&err_handler);CHKERRQ(ierr);
495     ierr = MPI_Errhandler_set(comm,err_handler);CHKERRQ(ierr);
496     ierr = PetscPushErrorHandler(PetscAttachDebuggerErrorHandler,0);CHKERRQ(ierr);
497   }
498   ierr = PetscOptionsGetString(PETSC_NULL,"-debug_terminal",string,64,&flg1);CHKERRQ(ierr);
499   if (flg1) { ierr = PetscSetDebugTerminal(string);CHKERRQ(ierr); }
500   ierr = PetscOptionsGetString(PETSC_NULL,"-start_in_debugger",string,64,&flg1);CHKERRQ(ierr);
501   ierr = PetscOptionsGetString(PETSC_NULL,"-stop_for_debugger",string,64,&flg2);CHKERRQ(ierr);
502   if (flg1 || flg2) {
503     PetscMPIInt    size;
504     PetscInt       lsize,*nodes;
505     MPI_Errhandler err_handler;
506     /*
507        we have to make sure that all processors have opened
508        connections to all other processors, otherwise once the
509        debugger has stated it is likely to receive a SIGUSR1
510        and kill the program.
511     */
512     ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
513     if (size > 2) {
514       PetscMPIInt dummy = 0;
515       MPI_Status  status;
516       for (i=0; i<size; i++) {
517         if (rank != i) {
518           ierr = MPI_Send(&dummy,1,MPI_INT,i,109,PETSC_COMM_WORLD);CHKERRQ(ierr);
519         }
520       }
521       for (i=0; i<size; i++) {
522         if (rank != i) {
523           ierr = MPI_Recv(&dummy,1,MPI_INT,i,109,PETSC_COMM_WORLD,&status);CHKERRQ(ierr);
524         }
525       }
526     }
527     /* check if this processor node should be in debugger */
528     ierr  = PetscMalloc(size*sizeof(PetscInt),&nodes);CHKERRQ(ierr);
529     lsize = size;
530     ierr  = PetscOptionsGetIntArray(PETSC_NULL,"-debugger_nodes",nodes,&lsize,&flag);CHKERRQ(ierr);
531     if (flag) {
532       for (i=0; i<lsize; i++) {
533         if (nodes[i] == rank) { flag = PETSC_FALSE; break; }
534       }
535     }
536     if (!flag) {
537       ierr = PetscSetDebuggerFromString(string);CHKERRQ(ierr);
538       ierr = PetscPushErrorHandler(PetscAbortErrorHandler,0);CHKERRQ(ierr);
539       if (flg1) {
540         ierr = PetscAttachDebugger();CHKERRQ(ierr);
541       } else {
542         ierr = PetscStopForDebugger();CHKERRQ(ierr);
543       }
544       ierr = MPI_Errhandler_create((MPI_Handler_function*)Petsc_MPI_AbortOnError,&err_handler);CHKERRQ(ierr);
545       ierr = MPI_Errhandler_set(comm,err_handler);CHKERRQ(ierr);
546     }
547     ierr = PetscFree(nodes);CHKERRQ(ierr);
548   }
549 
550   ierr = PetscOptionsGetString(PETSC_NULL,"-on_error_emacs",emacsmachinename,128,&flg1);CHKERRQ(ierr);
551   if (flg1 && !rank) {ierr = PetscPushErrorHandler(PetscEmacsClientErrorHandler,emacsmachinename);CHKERRQ(ierr);}
552 
553 #if defined(PETSC_USE_SOCKET_VIEWER)
554   /*
555     Activates new sockets for zope if needed
556   */
557   ierr = PetscOptionsHasName(PETSC_NULL,"-zope", &flgz);CHKERRQ(ierr);
558   ierr = PetscOptionsHasName(PETSC_NULL,"-nostdout", &flgzout);CHKERRQ(ierr);
559   if (flgz){
560     int  sockfd;
561     char hostname[256];
562     char username[256];
563     int  remoteport = 9999;
564 
565     ierr = PetscOptionsGetString(PETSC_NULL, "-zope", hostname, 256, &flgz);CHKERRQ(ierr);
566     if (!hostname[0]){
567       ierr = PetscGetHostName(hostname,256);CHKERRQ(ierr);
568     }
569     ierr = PetscOpenSocket(hostname, remoteport, &sockfd);CHKERRQ(ierr);
570     ierr = PetscGetUserName(username, 256);CHKERRQ(ierr);
571     PETSC_ZOPEFD = fdopen(sockfd, "w");
572     if (flgzout){
573       PETSC_STDOUT = PETSC_ZOPEFD;
574       fprintf(PETSC_STDOUT, "<<<user>>> %s\n",username);
575       fprintf(PETSC_STDOUT, "<<<start>>>");
576     } else {
577       fprintf(PETSC_ZOPEFD, "<<<user>>> %s\n",username);
578       fprintf(PETSC_ZOPEFD, "<<<start>>>");
579     }
580   }
581 #endif
582 #if defined(PETSC_USE_SERVER)
583   ierr = PetscOptionsHasName(PETSC_NULL,"-server", &flgz);CHKERRQ(ierr);
584   if (flgz){
585     PetscInt port = PETSC_DECIDE;
586     ierr = PetscOptionsGetInt(PETSC_NULL,"-server",&port,PETSC_NULL);CHKERRQ(ierr);
587     ierr = PetscWebServe(PETSC_COMM_WORLD,(int)port);CHKERRQ(ierr);
588   }
589 #endif
590 
591   /*
592         Setup profiling and logging
593   */
594 #if defined (PETSC_USE_INFO)
595   {
596     char logname[PETSC_MAX_PATH_LEN]; logname[0] = 0;
597     ierr = PetscOptionsGetString(PETSC_NULL,"-info",logname,250,&flg1);CHKERRQ(ierr);
598     if (flg1 && logname[0]) {
599       ierr = PetscInfoAllow(PETSC_TRUE,logname);CHKERRQ(ierr);
600     } else if (flg1) {
601       ierr = PetscInfoAllow(PETSC_TRUE,PETSC_NULL);CHKERRQ(ierr);
602     }
603   }
604 #endif
605 #if defined(PETSC_USE_LOG)
606   mname[0] = 0;
607   ierr = PetscOptionsGetString(PETSC_NULL,"-history",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
608   if (flg1) {
609     if (mname[0]) {
610       ierr = PetscOpenHistoryFile(mname,&petsc_history);CHKERRQ(ierr);
611     } else {
612       ierr = PetscOpenHistoryFile(0,&petsc_history);CHKERRQ(ierr);
613     }
614   }
615 #if defined(PETSC_HAVE_MPE)
616   flg1 = PETSC_FALSE;
617   ierr = PetscOptionsHasName(PETSC_NULL,"-log_mpe",&flg1);CHKERRQ(ierr);
618   if (flg1) PetscLogMPEBegin();
619 #endif
620   flg1 = PETSC_FALSE;
621   flg2 = PETSC_FALSE;
622   flg3 = PETSC_FALSE;
623   ierr = PetscOptionsGetBool(PETSC_NULL,"-log_all",&flg1,PETSC_NULL);CHKERRQ(ierr);
624   ierr = PetscOptionsGetBool(PETSC_NULL,"-log",&flg2,PETSC_NULL);CHKERRQ(ierr);
625   ierr = PetscOptionsHasName(PETSC_NULL,"-log_summary",&flg3);CHKERRQ(ierr);
626   ierr = PetscOptionsHasName(PETSC_NULL,"-log_summary_python",&flg4);CHKERRQ(ierr);
627   if (flg1)                      {  ierr = PetscLogAllBegin();CHKERRQ(ierr); }
628   else if (flg2 || flg3 || flg4) {  ierr = PetscLogBegin();CHKERRQ(ierr);}
629 
630   ierr = PetscOptionsGetString(PETSC_NULL,"-log_trace",mname,250,&flg1);CHKERRQ(ierr);
631   if (flg1) {
632     char name[PETSC_MAX_PATH_LEN],fname[PETSC_MAX_PATH_LEN];
633     FILE *file;
634     if (mname[0]) {
635       sprintf(name,"%s.%d",mname,rank);
636       ierr = PetscFixFilename(name,fname);CHKERRQ(ierr);
637       file = fopen(fname,"w");
638       if (!file) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open trace file: %s",fname);
639     } else {
640       file = PETSC_STDOUT;
641     }
642     ierr = PetscLogTraceBegin(file);CHKERRQ(ierr);
643   }
644 #endif
645 
646   /*
647       Setup building of stack frames for all function calls
648   */
649 #if defined(PETSC_USE_DEBUG) && !defined(PETSC_USE_PTHREAD)
650   ierr = PetscStackCreate();CHKERRQ(ierr);
651 #endif
652 
653   ierr = PetscOptionsGetBool(PETSC_NULL,"-options_gui",&PetscOptionsPublish,PETSC_NULL);CHKERRQ(ierr);
654 
655 #if defined(PETSC_HAVE_PTHREADCLASSES)
656   /*
657       Determine whether user specified maximum number of threads
658    */
659   ierr = PetscOptionsGetInt(PETSC_NULL,"-thread_max",&PetscMaxThreads,PETSC_NULL);CHKERRQ(ierr);
660 
661   ierr = PetscOptionsHasName(PETSC_NULL,"-main",&flg1);CHKERRQ(ierr);
662   if(flg1) {
663     cpu_set_t mset;
664     int icorr,ncorr = get_nprocs();
665     ierr = PetscOptionsGetInt(PETSC_NULL,"-main",&icorr,PETSC_NULL);CHKERRQ(ierr);
666     CPU_ZERO(&mset);
667     CPU_SET(icorr%ncorr,&mset);
668     sched_setaffinity(0,sizeof(cpu_set_t),&mset);
669   }
670 
671   PetscInt N_CORES = get_nprocs();
672   ThreadCoreAffinity = (int*)malloc(N_CORES*sizeof(int));
673   char tstr[9];
674   char tbuf[2];
675   strcpy(tstr,"-thread");
676   for(i=0;i<PetscMaxThreads;i++) {
677     ThreadCoreAffinity[i] = i;
678     sprintf(tbuf,"%d",i);
679     strcat(tstr,tbuf);
680     ierr = PetscOptionsHasName(PETSC_NULL,tstr,&flg1);CHKERRQ(ierr);
681     if(flg1) {
682       ierr = PetscOptionsGetInt(PETSC_NULL,tstr,&ThreadCoreAffinity[i],PETSC_NULL);CHKERRQ(ierr);
683       ThreadCoreAffinity[i] = ThreadCoreAffinity[i]%N_CORES; /* check on the user */
684     }
685     tstr[7] = '\0';
686   }
687 
688   /*
689       Determine whether to use thread pool
690    */
691   ierr = PetscOptionsHasName(PETSC_NULL,"-use_thread_pool",&flg1);CHKERRQ(ierr);
692   if (flg1) {
693     PetscUseThreadPool = PETSC_TRUE;
694     /* get the thread pool type */
695     PetscInt ipool = 0;
696     const char *choices[4] = {"true","tree","main","chain"};
697 
698     ierr = PetscOptionsGetEList(PETSC_NULL,"-use_thread_pool",choices,4,&ipool,PETSC_NULL);CHKERRQ(ierr);
699     switch(ipool) {
700     case 1:
701       PetscThreadFunc       = &PetscThreadFunc_Tree;
702       PetscThreadInitialize = &PetscThreadInitialize_Tree;
703       PetscThreadFinalize   = &PetscThreadFinalize_Tree;
704       MainWait              = &MainWait_Tree;
705       MainJob               = &MainJob_Tree;
706       PetscInfo(PETSC_NULL,"Using tree thread pool\n");
707       break;
708     case 2:
709       PetscThreadFunc       = &PetscThreadFunc_Main;
710       PetscThreadInitialize = &PetscThreadInitialize_Main;
711       PetscThreadFinalize   = &PetscThreadFinalize_Main;
712       MainWait              = &MainWait_Main;
713       MainJob               = &MainJob_Main;
714       PetscInfo(PETSC_NULL,"Using main thread pool\n");
715       break;
716 #if defined(PETSC_HAVE_PTHREAD_BARRIER)
717     case 3:
718 #else
719     default:
720 #endif
721       PetscThreadFunc       = &PetscThreadFunc_Chain;
722       PetscThreadInitialize = &PetscThreadInitialize_Chain;
723       PetscThreadFinalize   = &PetscThreadFinalize_Chain;
724       MainWait              = &MainWait_Chain;
725       MainJob               = &MainJob_Chain;
726       PetscInfo(PETSC_NULL,"Using chain thread pool\n");
727       break;
728 #if defined(PETSC_HAVE_PTHREAD_BARRIER)
729     default:
730       PetscThreadFunc       = &PetscThreadFunc_True;
731       PetscThreadInitialize = &PetscThreadInitialize_True;
732       PetscThreadFinalize   = &PetscThreadFinalize_True;
733       MainWait              = &MainWait_True;
734       MainJob               = &MainJob_True;
735       PetscInfo(PETSC_NULL,"Using true thread pool\n");
736       break;
737 #endif
738     }
739     PetscThreadInitialize(PetscMaxThreads);
740   } else {
741     //need to define these in the case on 'no threads' or 'thread create/destroy'
742     //could take any of the above versions
743     MainJob               = &MainJob_Spawn;
744   }
745 #endif
746   /*
747        Print basic help message
748   */
749   ierr = PetscOptionsHasName(PETSC_NULL,"-help",&flg1);CHKERRQ(ierr);
750   if (flg1) {
751     ierr = (*PetscHelpPrintf)(comm,"Options for all PETSc programs:\n");CHKERRQ(ierr);
752     ierr = (*PetscHelpPrintf)(comm," -help: prints help method for each option\n");CHKERRQ(ierr);
753     ierr = (*PetscHelpPrintf)(comm," -on_error_abort: cause an abort when an error is detected. Useful \n ");CHKERRQ(ierr);
754     ierr = (*PetscHelpPrintf)(comm,"       only when run in the debugger\n");CHKERRQ(ierr);
755     ierr = (*PetscHelpPrintf)(comm," -on_error_attach_debugger [gdb,dbx,xxgdb,ups,noxterm]\n");CHKERRQ(ierr);
756     ierr = (*PetscHelpPrintf)(comm,"       start the debugger in new xterm\n");CHKERRQ(ierr);
757     ierr = (*PetscHelpPrintf)(comm,"       unless noxterm is given\n");CHKERRQ(ierr);
758     ierr = (*PetscHelpPrintf)(comm," -start_in_debugger [gdb,dbx,xxgdb,ups,noxterm]\n");CHKERRQ(ierr);
759     ierr = (*PetscHelpPrintf)(comm,"       start all processes in the debugger\n");CHKERRQ(ierr);
760     ierr = (*PetscHelpPrintf)(comm," -on_error_emacs <machinename>\n");CHKERRQ(ierr);
761     ierr = (*PetscHelpPrintf)(comm,"    emacs jumps to error file\n");CHKERRQ(ierr);
762     ierr = (*PetscHelpPrintf)(comm," -debugger_nodes [n1,n2,..] Nodes to start in debugger\n");CHKERRQ(ierr);
763     ierr = (*PetscHelpPrintf)(comm," -debugger_pause [m] : delay (in seconds) to attach debugger\n");CHKERRQ(ierr);
764     ierr = (*PetscHelpPrintf)(comm," -stop_for_debugger : prints message on how to attach debugger manually\n");CHKERRQ(ierr);
765     ierr = (*PetscHelpPrintf)(comm,"                      waits the delay for you to attach\n");CHKERRQ(ierr);
766     ierr = (*PetscHelpPrintf)(comm," -display display: Location where graphics and debuggers are displayed\n");CHKERRQ(ierr);
767     ierr = (*PetscHelpPrintf)(comm," -no_signal_handler: do not trap error signals\n");CHKERRQ(ierr);
768     ierr = (*PetscHelpPrintf)(comm," -mpi_return_on_error: MPI returns error code, rather than abort on internal error\n");CHKERRQ(ierr);
769     ierr = (*PetscHelpPrintf)(comm," -fp_trap: stop on floating point exceptions\n");CHKERRQ(ierr);
770     ierr = (*PetscHelpPrintf)(comm,"           note on IBM RS6000 this slows run greatly\n");CHKERRQ(ierr);
771     ierr = (*PetscHelpPrintf)(comm," -malloc_dump <optional filename>: dump list of unfreed memory at conclusion\n");CHKERRQ(ierr);
772     ierr = (*PetscHelpPrintf)(comm," -malloc: use our error checking malloc\n");CHKERRQ(ierr);
773     ierr = (*PetscHelpPrintf)(comm," -malloc no: don't use error checking malloc\n");CHKERRQ(ierr);
774     ierr = (*PetscHelpPrintf)(comm," -malloc_info: prints total memory usage\n");CHKERRQ(ierr);
775     ierr = (*PetscHelpPrintf)(comm," -malloc_log: keeps log of all memory allocations\n");CHKERRQ(ierr);
776     ierr = (*PetscHelpPrintf)(comm," -malloc_debug: enables extended checking for memory corruption\n");CHKERRQ(ierr);
777     ierr = (*PetscHelpPrintf)(comm," -options_table: dump list of options inputted\n");CHKERRQ(ierr);
778     ierr = (*PetscHelpPrintf)(comm," -options_left: dump list of unused options\n");CHKERRQ(ierr);
779     ierr = (*PetscHelpPrintf)(comm," -options_left no: don't dump list of unused options\n");CHKERRQ(ierr);
780     ierr = (*PetscHelpPrintf)(comm," -tmp tmpdir: alternative /tmp directory\n");CHKERRQ(ierr);
781     ierr = (*PetscHelpPrintf)(comm," -shared_tmp: tmp directory is shared by all processors\n");CHKERRQ(ierr);
782     ierr = (*PetscHelpPrintf)(comm," -not_shared_tmp: each processor has separate tmp directory\n");CHKERRQ(ierr);
783     ierr = (*PetscHelpPrintf)(comm," -memory_info: print memory usage at end of run\n");CHKERRQ(ierr);
784     ierr = (*PetscHelpPrintf)(comm," -server <port>: Run PETSc webserver (default port is 8080) see PetscWebServe()\n");CHKERRQ(ierr);
785 #if defined(PETSC_USE_LOG)
786     ierr = (*PetscHelpPrintf)(comm," -get_total_flops: total flops over all processors\n");CHKERRQ(ierr);
787     ierr = (*PetscHelpPrintf)(comm," -log[_all _summary _summary_python]: logging objects and events\n");CHKERRQ(ierr);
788     ierr = (*PetscHelpPrintf)(comm," -log_trace [filename]: prints trace of all PETSc calls\n");CHKERRQ(ierr);
789 #if defined(PETSC_HAVE_MPE)
790     ierr = (*PetscHelpPrintf)(comm," -log_mpe: Also create logfile viewable through upshot\n");CHKERRQ(ierr);
791 #endif
792     ierr = (*PetscHelpPrintf)(comm," -info <optional filename>: print informative messages about the calculations\n");CHKERRQ(ierr);
793 #endif
794     ierr = (*PetscHelpPrintf)(comm," -v: prints PETSc version number and release date\n");CHKERRQ(ierr);
795     ierr = (*PetscHelpPrintf)(comm," -options_file <file>: reads options from file\n");CHKERRQ(ierr);
796     ierr = (*PetscHelpPrintf)(comm," -petsc_sleep n: sleeps n seconds before running program\n");CHKERRQ(ierr);
797     ierr = (*PetscHelpPrintf)(comm,"-----------------------------------------------\n");CHKERRQ(ierr);
798   }
799 
800   ierr = PetscOptionsGetReal(PETSC_NULL,"-petsc_sleep",&si,&flg1);CHKERRQ(ierr);
801   if (flg1) {
802     ierr = PetscSleep(si);CHKERRQ(ierr);
803   }
804 
805   ierr = PetscOptionsGetString(PETSC_NULL,"-info_exclude",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
806   ierr = PetscStrstr(mname,"null",&f);CHKERRQ(ierr);
807   if (f) {
808     ierr = PetscInfoDeactivateClass(PETSC_NULL);CHKERRQ(ierr);
809   }
810 
811 #if defined(PETSC_HAVE_CUSP)
812   ierr = PetscOptionsHasName(PETSC_NULL,"-log_summary",&flg3);CHKERRQ(ierr);
813   if (flg3) flg1 = PETSC_TRUE;
814   else flg1 = PETSC_FALSE;
815   ierr = PetscOptionsGetBool(PETSC_NULL,"-cusp_synchronize",&flg1,PETSC_NULL);CHKERRQ(ierr);
816   if (flg1) synchronizeCUSP = PETSC_TRUE;
817 #endif
818 
819   PetscFunctionReturn(0);
820 }
821 
822 #if defined(PETSC_HAVE_PTHREADCLASSES)
823 
824 /**** 'Tree' Thread Pool Functions ****/
825 void* PetscThreadFunc_Tree(void* arg) {
826   PetscErrorCode iterr;
827   int icorr,ierr;
828   int* pId = (int*)arg;
829   int ThreadId = *pId,Mary = 2,i,SubWorker;
830   PetscBool PeeOn;
831   cpu_set_t mset;
832   //printf("Thread %d In Tree Thread Function\n",ThreadId);
833   icorr = ThreadCoreAffinity[ThreadId];
834   CPU_ZERO(&mset);
835   CPU_SET(icorr,&mset);
836   sched_setaffinity(0,sizeof(cpu_set_t),&mset);
837 
838   if((Mary*ThreadId+1)>(PetscMaxThreads-1)) {
839     PeeOn = PETSC_TRUE;
840   }
841   else {
842     PeeOn = PETSC_FALSE;
843   }
844   if(PeeOn==PETSC_FALSE) {
845     /* check your subordinates, wait for them to be ready */
846     for(i=1;i<=Mary;i++) {
847       SubWorker = Mary*ThreadId+i;
848       if(SubWorker<PetscMaxThreads) {
849         ierr = pthread_mutex_lock(job_tree.mutexarray[SubWorker]);
850         while(*(job_tree.arrThreadReady[SubWorker])==PETSC_FALSE) {
851           /* upon entry, automically releases the lock and blocks
852            upon return, has the lock */
853           ierr = pthread_cond_wait(job_tree.cond1array[SubWorker],job_tree.mutexarray[SubWorker]);
854         }
855         ierr = pthread_mutex_unlock(job_tree.mutexarray[SubWorker]);
856       }
857     }
858     /* your subordinates are now ready */
859   }
860   ierr = pthread_mutex_lock(job_tree.mutexarray[ThreadId]);
861   /* update your ready status */
862   *(job_tree.arrThreadReady[ThreadId]) = PETSC_TRUE;
863   if(ThreadId==0) {
864     job_tree.eJobStat = JobCompleted;
865     /* ignal main */
866     ierr = pthread_cond_signal(&main_cond);
867   }
868   else {
869     /* tell your boss that you're ready to work */
870     ierr = pthread_cond_signal(job_tree.cond1array[ThreadId]);
871   }
872   /* the while loop needs to have an exit
873   the 'main' thread can terminate all the threads by performing a broadcast
874    and calling FuncFinish */
875   while(PetscThreadGo) {
876     /*need to check the condition to ensure we don't have to wait
877       waiting when you don't have to causes problems
878      also need to check the condition to ensure proper handling of spurious wakeups */
879     while(*(job_tree.arrThreadReady[ThreadId])==PETSC_TRUE) {
880       /* upon entry, automically releases the lock and blocks
881        upon return, has the lock */
882         ierr = pthread_cond_wait(job_tree.cond2array[ThreadId],job_tree.mutexarray[ThreadId]);
883 	*(job_tree.arrThreadStarted[ThreadId]) = PETSC_TRUE;
884 	*(job_tree.arrThreadReady[ThreadId])   = PETSC_FALSE;
885     }
886     if(ThreadId==0) {
887       job_tree.startJob = PETSC_FALSE;
888       job_tree.eJobStat = ThreadsWorking;
889     }
890     ierr = pthread_mutex_unlock(job_tree.mutexarray[ThreadId]);
891     if(PeeOn==PETSC_FALSE) {
892       /* tell your subordinates it's time to get to work */
893       for(i=1; i<=Mary; i++) {
894 	SubWorker = Mary*ThreadId+i;
895         if(SubWorker<PetscMaxThreads) {
896           ierr = pthread_cond_signal(job_tree.cond2array[SubWorker]);
897         }
898       }
899     }
900     /* do your job */
901     if(job_tree.pdata==NULL) {
902       iterr = (PetscErrorCode)(long int)job_tree.pfunc(job_tree.pdata);
903     }
904     else {
905       iterr = (PetscErrorCode)(long int)job_tree.pfunc(job_tree.pdata[ThreadId]);
906     }
907     if(iterr!=0) {
908       ithreaderr = 1;
909     }
910     if(PetscThreadGo) {
911       /* reset job, get ready for more */
912       if(PeeOn==PETSC_FALSE) {
913         /* check your subordinates, waiting for them to be ready
914          how do you know for a fact that a given subordinate has actually started? */
915 	for(i=1;i<=Mary;i++) {
916 	  SubWorker = Mary*ThreadId+i;
917           if(SubWorker<PetscMaxThreads) {
918             ierr = pthread_mutex_lock(job_tree.mutexarray[SubWorker]);
919             while(*(job_tree.arrThreadReady[SubWorker])==PETSC_FALSE||*(job_tree.arrThreadStarted[SubWorker])==PETSC_FALSE) {
920               /* upon entry, automically releases the lock and blocks
921                upon return, has the lock */
922               ierr = pthread_cond_wait(job_tree.cond1array[SubWorker],job_tree.mutexarray[SubWorker]);
923             }
924             ierr = pthread_mutex_unlock(job_tree.mutexarray[SubWorker]);
925           }
926 	}
927         /* your subordinates are now ready */
928       }
929       ierr = pthread_mutex_lock(job_tree.mutexarray[ThreadId]);
930       *(job_tree.arrThreadReady[ThreadId]) = PETSC_TRUE;
931       if(ThreadId==0) {
932 	job_tree.eJobStat = JobCompleted; /* oot thread: last thread to complete, guaranteed! */
933         /* root thread signals 'main' */
934         ierr = pthread_cond_signal(&main_cond);
935       }
936       else {
937         /* signal your boss before you go to sleep */
938         ierr = pthread_cond_signal(job_tree.cond1array[ThreadId]);
939       }
940     }
941   }
942   return NULL;
943 }
944 
945 #undef __FUNCT__
946 #define __FUNCT__ "PetscThreadInitialize_Tree"
947 void* PetscThreadInitialize_Tree(PetscInt N) {
948   PetscInt i,ierr;
949   int status;
950 
951   if(PetscUseThreadPool) {
952     size_t Val1 = (size_t)CACHE_LINE_SIZE;
953     size_t Val2 = (size_t)PetscMaxThreads*CACHE_LINE_SIZE;
954     arrmutex = (char*)memalign(Val1,Val2);
955     arrcond1 = (char*)memalign(Val1,Val2);
956     arrcond2 = (char*)memalign(Val1,Val2);
957     arrstart = (char*)memalign(Val1,Val2);
958     arrready = (char*)memalign(Val1,Val2);
959     job_tree.mutexarray       = (pthread_mutex_t**)malloc(PetscMaxThreads*sizeof(pthread_mutex_t*));
960     job_tree.cond1array       = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*));
961     job_tree.cond2array       = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*));
962     job_tree.arrThreadStarted = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*));
963     job_tree.arrThreadReady   = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*));
964     /* initialize job structure */
965     for(i=0; i<PetscMaxThreads; i++) {
966       job_tree.mutexarray[i]        = (pthread_mutex_t*)(arrmutex+CACHE_LINE_SIZE*i);
967       job_tree.cond1array[i]        = (pthread_cond_t*)(arrcond1+CACHE_LINE_SIZE*i);
968       job_tree.cond2array[i]        = (pthread_cond_t*)(arrcond2+CACHE_LINE_SIZE*i);
969       job_tree.arrThreadStarted[i]  = (PetscBool*)(arrstart+CACHE_LINE_SIZE*i);
970       job_tree.arrThreadReady[i]    = (PetscBool*)(arrready+CACHE_LINE_SIZE*i);
971     }
972     for(i=0; i<PetscMaxThreads; i++) {
973       ierr = pthread_mutex_init(job_tree.mutexarray[i],NULL);
974       ierr = pthread_cond_init(job_tree.cond1array[i],NULL);
975       ierr = pthread_cond_init(job_tree.cond2array[i],NULL);
976       *(job_tree.arrThreadStarted[i])  = PETSC_FALSE;
977       *(job_tree.arrThreadReady[i])    = PETSC_FALSE;
978     }
979     job_tree.pfunc = NULL;
980     job_tree.pdata = (void**)malloc(N*sizeof(void*));
981     job_tree.startJob = PETSC_FALSE;
982     job_tree.eJobStat = JobInitiated;
983     pVal = (int*)malloc(N*sizeof(int));
984     /* allocate memory in the heap for the thread structure */
985     PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t));
986     /* create threads */
987     for(i=0; i<N; i++) {
988       pVal[i] = i;
989       status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]);
990       /* should check status */
991     }
992   }
993   return NULL;
994 }
995 
996 #undef __FUNCT__
997 #define __FUNCT__ "PetscThreadFinalize_Tree"
998 PetscErrorCode PetscThreadFinalize_Tree() {
999   int i,ierr;
1000   void* jstatus;
1001 
1002   PetscFunctionBegin;
1003 
1004   MainJob(FuncFinish,NULL,PetscMaxThreads);  /* set up job and broadcast work */
1005   /* join the threads */
1006   for(i=0; i<PetscMaxThreads; i++) {
1007     ierr = pthread_join(PetscThreadPoint[i],&jstatus);
1008     /* do error checking*/
1009   }
1010   free(PetscThreadPoint);
1011   free(arrmutex);
1012   free(arrcond1);
1013   free(arrcond2);
1014   free(arrstart);
1015   free(arrready);
1016   free(job_tree.pdata);
1017   free(pVal);
1018 
1019   PetscFunctionReturn(0);
1020 }
1021 
1022 #undef __FUNCT__
1023 #define __FUNCT__ "MainWait_Tree"
1024 void MainWait_Tree() {
1025   int ierr;
1026   ierr = pthread_mutex_lock(job_tree.mutexarray[0]);
1027   while(job_tree.eJobStat<JobCompleted||job_tree.startJob==PETSC_TRUE) {
1028     ierr = pthread_cond_wait(&main_cond,job_tree.mutexarray[0]);
1029   }
1030   ierr = pthread_mutex_unlock(job_tree.mutexarray[0]);
1031 }
1032 
1033 #undef __FUNCT__
1034 #define __FUNCT__ "MainJob_Tree"
1035 PetscErrorCode MainJob_Tree(void* (*pFunc)(void*),void** data,PetscInt n) {
1036   int i,ierr;
1037   PetscErrorCode ijoberr = 0;
1038 
1039   MainWait();
1040   job_tree.pfunc = pFunc;
1041   job_tree.pdata = data;
1042   job_tree.startJob = PETSC_TRUE;
1043   for(i=0; i<PetscMaxThreads; i++) {
1044     *(job_tree.arrThreadStarted[i]) = PETSC_FALSE;
1045   }
1046   job_tree.eJobStat = JobInitiated;
1047   ierr = pthread_cond_signal(job_tree.cond2array[0]);
1048   if(pFunc!=FuncFinish) {
1049     MainWait(); /* why wait after? guarantees that job gets done before proceeding with result collection (if any) */
1050   }
1051 
1052   if(ithreaderr) {
1053     ijoberr = ithreaderr;
1054   }
1055   return ijoberr;
1056 }
1057 /****  ****/
1058 
1059 /**** 'Main' Thread Pool Functions ****/
1060 void* PetscThreadFunc_Main(void* arg) {
1061   PetscErrorCode iterr;
1062   int icorr,ierr;
1063   int* pId = (int*)arg;
1064   int ThreadId = *pId;
1065   cpu_set_t mset;
1066   //printf("Thread %d In Main Thread Function\n",ThreadId);
1067   icorr = ThreadCoreAffinity[ThreadId];
1068   CPU_ZERO(&mset);
1069   CPU_SET(icorr,&mset);
1070   sched_setaffinity(0,sizeof(cpu_set_t),&mset);
1071 
1072   ierr = pthread_mutex_lock(job_main.mutexarray[ThreadId]);
1073   /* update your ready status */
1074   *(job_main.arrThreadReady[ThreadId]) = PETSC_TRUE;
1075   /* tell the BOSS that you're ready to work before you go to sleep */
1076   ierr = pthread_cond_signal(job_main.cond1array[ThreadId]);
1077 
1078   /* the while loop needs to have an exit
1079      the 'main' thread can terminate all the threads by performing a broadcast
1080      and calling FuncFinish */
1081   while(PetscThreadGo) {
1082     /* need to check the condition to ensure we don't have to wait
1083        waiting when you don't have to causes problems
1084      also need to check the condition to ensure proper handling of spurious wakeups */
1085     while(*(job_main.arrThreadReady[ThreadId])==PETSC_TRUE) {
1086       /* upon entry, atomically releases the lock and blocks
1087        upon return, has the lock */
1088         ierr = pthread_cond_wait(job_main.cond2array[ThreadId],job_main.mutexarray[ThreadId]);
1089 	/* (job_main.arrThreadReady[ThreadId])   = PETSC_FALSE; */
1090     }
1091     ierr = pthread_mutex_unlock(job_main.mutexarray[ThreadId]);
1092     if(job_main.pdata==NULL) {
1093       iterr = (PetscErrorCode)(long int)job_main.pfunc(job_main.pdata);
1094     }
1095     else {
1096       iterr = (PetscErrorCode)(long int)job_main.pfunc(job_main.pdata[ThreadId]);
1097     }
1098     if(iterr!=0) {
1099       ithreaderr = 1;
1100     }
1101     if(PetscThreadGo) {
1102       /* reset job, get ready for more */
1103       ierr = pthread_mutex_lock(job_main.mutexarray[ThreadId]);
1104       *(job_main.arrThreadReady[ThreadId]) = PETSC_TRUE;
1105       /* tell the BOSS that you're ready to work before you go to sleep */
1106       ierr = pthread_cond_signal(job_main.cond1array[ThreadId]);
1107     }
1108   }
1109   return NULL;
1110 }
1111 
1112 #undef __FUNCT__
1113 #define __FUNCT__ "PetscThreadInitialize_Main"
1114 void* PetscThreadInitialize_Main(PetscInt N) {
1115   PetscInt i,ierr;
1116   int status;
1117 
1118   if(PetscUseThreadPool) {
1119     size_t Val1 = (size_t)CACHE_LINE_SIZE;
1120     size_t Val2 = (size_t)PetscMaxThreads*CACHE_LINE_SIZE;
1121     arrmutex = (char*)memalign(Val1,Val2);
1122     arrcond1 = (char*)memalign(Val1,Val2);
1123     arrcond2 = (char*)memalign(Val1,Val2);
1124     arrstart = (char*)memalign(Val1,Val2);
1125     arrready = (char*)memalign(Val1,Val2);
1126     job_main.mutexarray       = (pthread_mutex_t**)malloc(PetscMaxThreads*sizeof(pthread_mutex_t*));
1127     job_main.cond1array       = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*));
1128     job_main.cond2array       = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*));
1129     job_main.arrThreadReady   = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*));
1130     /* initialize job structure */
1131     for(i=0; i<PetscMaxThreads; i++) {
1132       job_main.mutexarray[i]        = (pthread_mutex_t*)(arrmutex+CACHE_LINE_SIZE*i);
1133       job_main.cond1array[i]        = (pthread_cond_t*)(arrcond1+CACHE_LINE_SIZE*i);
1134       job_main.cond2array[i]        = (pthread_cond_t*)(arrcond2+CACHE_LINE_SIZE*i);
1135       job_main.arrThreadReady[i]    = (PetscBool*)(arrready+CACHE_LINE_SIZE*i);
1136     }
1137     for(i=0; i<PetscMaxThreads; i++) {
1138       ierr = pthread_mutex_init(job_main.mutexarray[i],NULL);
1139       ierr = pthread_cond_init(job_main.cond1array[i],NULL);
1140       ierr = pthread_cond_init(job_main.cond2array[i],NULL);
1141       *(job_main.arrThreadReady[i])    = PETSC_FALSE;
1142     }
1143     job_main.pfunc = NULL;
1144     job_main.pdata = (void**)malloc(N*sizeof(void*));
1145     pVal = (int*)malloc(N*sizeof(int));
1146     /* allocate memory in the heap for the thread structure */
1147     PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t));
1148     /* create threads */
1149     for(i=0; i<N; i++) {
1150       pVal[i] = i;
1151       status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]);
1152       /* error check */
1153     }
1154   }
1155   else {
1156   }
1157   return NULL;
1158 }
1159 
1160 #undef __FUNCT__
1161 #define __FUNCT__ "PetscThreadFinalize_Main"
1162 PetscErrorCode PetscThreadFinalize_Main() {
1163   int i,ierr;
1164   void* jstatus;
1165 
1166   PetscFunctionBegin;
1167 
1168   MainJob(FuncFinish,NULL,PetscMaxThreads);  /* set up job and broadcast work */
1169   /* join the threads */
1170   for(i=0; i<PetscMaxThreads; i++) {
1171     ierr = pthread_join(PetscThreadPoint[i],&jstatus);CHKERRQ(ierr);
1172   }
1173   free(PetscThreadPoint);
1174   free(arrmutex);
1175   free(arrcond1);
1176   free(arrcond2);
1177   free(arrstart);
1178   free(arrready);
1179   free(job_main.pdata);
1180   free(pVal);
1181 
1182   PetscFunctionReturn(0);
1183 }
1184 
1185 #undef __FUNCT__
1186 #define __FUNCT__ "MainWait_Main"
1187 void MainWait_Main() {
1188   int i,ierr;
1189   for(i=0; i<PetscMaxThreads; i++) {
1190     ierr = pthread_mutex_lock(job_main.mutexarray[i]);
1191     while(*(job_main.arrThreadReady[i])==PETSC_FALSE) {
1192       ierr = pthread_cond_wait(job_main.cond1array[i],job_main.mutexarray[i]);
1193     }
1194     ierr = pthread_mutex_unlock(job_main.mutexarray[i]);
1195   }
1196 }
1197 
1198 #undef __FUNCT__
1199 #define __FUNCT__ "MainJob_Main"
1200 PetscErrorCode MainJob_Main(void* (*pFunc)(void*),void** data,PetscInt n) {
1201   int i,ierr;
1202   PetscErrorCode ijoberr = 0;
1203 
1204   MainWait(); /* you know everyone is waiting to be signalled! */
1205   job_main.pfunc = pFunc;
1206   job_main.pdata = data;
1207   for(i=0; i<PetscMaxThreads; i++) {
1208     *(job_main.arrThreadReady[i]) = PETSC_FALSE; /* why do this?  suppose you get into MainWait first */
1209   }
1210   /* tell the threads to go to work */
1211   for(i=0; i<PetscMaxThreads; i++) {
1212     ierr = pthread_cond_signal(job_main.cond2array[i]);
1213   }
1214   if(pFunc!=FuncFinish) {
1215     MainWait(); /* why wait after? guarantees that job gets done before proceeding with result collection (if any) */
1216   }
1217 
1218   if(ithreaderr) {
1219     ijoberr = ithreaderr;
1220   }
1221   return ijoberr;
1222 }
1223 /****  ****/
1224 
1225 /**** Chain Thread Functions ****/
1226 void* PetscThreadFunc_Chain(void* arg) {
1227   PetscErrorCode iterr;
1228   int icorr,ierr;
1229   int* pId = (int*)arg;
1230   int ThreadId = *pId;
1231   int SubWorker = ThreadId + 1;
1232   PetscBool PeeOn;
1233   cpu_set_t mset;
1234   //printf("Thread %d In Chain Thread Function\n",ThreadId);
1235   icorr = ThreadCoreAffinity[ThreadId];
1236   CPU_ZERO(&mset);
1237   CPU_SET(icorr,&mset);
1238   sched_setaffinity(0,sizeof(cpu_set_t),&mset);
1239 
1240   if(ThreadId==(PetscMaxThreads-1)) {
1241     PeeOn = PETSC_TRUE;
1242   }
1243   else {
1244     PeeOn = PETSC_FALSE;
1245   }
1246   if(PeeOn==PETSC_FALSE) {
1247     /* check your subordinate, wait for him to be ready */
1248     ierr = pthread_mutex_lock(job_chain.mutexarray[SubWorker]);
1249     while(*(job_chain.arrThreadReady[SubWorker])==PETSC_FALSE) {
1250       /* upon entry, automically releases the lock and blocks
1251        upon return, has the lock */
1252       ierr = pthread_cond_wait(job_chain.cond1array[SubWorker],job_chain.mutexarray[SubWorker]);
1253     }
1254     ierr = pthread_mutex_unlock(job_chain.mutexarray[SubWorker]);
1255     /* your subordinate is now ready*/
1256   }
1257   ierr = pthread_mutex_lock(job_chain.mutexarray[ThreadId]);
1258   /* update your ready status */
1259   *(job_chain.arrThreadReady[ThreadId]) = PETSC_TRUE;
1260   if(ThreadId==0) {
1261     job_chain.eJobStat = JobCompleted;
1262     /* signal main */
1263     ierr = pthread_cond_signal(&main_cond);
1264   }
1265   else {
1266     /* tell your boss that you're ready to work */
1267     ierr = pthread_cond_signal(job_chain.cond1array[ThreadId]);
1268   }
1269   /*  the while loop needs to have an exit
1270      the 'main' thread can terminate all the threads by performing a broadcast
1271    and calling FuncFinish */
1272   while(PetscThreadGo) {
1273     /* need to check the condition to ensure we don't have to wait
1274        waiting when you don't have to causes problems
1275      also need to check the condition to ensure proper handling of spurious wakeups */
1276     while(*(job_chain.arrThreadReady[ThreadId])==PETSC_TRUE) {
1277       /*upon entry, automically releases the lock and blocks
1278        upon return, has the lock */
1279         ierr = pthread_cond_wait(job_chain.cond2array[ThreadId],job_chain.mutexarray[ThreadId]);
1280 	*(job_chain.arrThreadStarted[ThreadId]) = PETSC_TRUE;
1281 	*(job_chain.arrThreadReady[ThreadId])   = PETSC_FALSE;
1282     }
1283     if(ThreadId==0) {
1284       job_chain.startJob = PETSC_FALSE;
1285       job_chain.eJobStat = ThreadsWorking;
1286     }
1287     ierr = pthread_mutex_unlock(job_chain.mutexarray[ThreadId]);
1288     if(PeeOn==PETSC_FALSE) {
1289       /* tell your subworker it's time to get to work */
1290       ierr = pthread_cond_signal(job_chain.cond2array[SubWorker]);
1291     }
1292     /* do your job */
1293     if(job_chain.pdata==NULL) {
1294       iterr = (PetscErrorCode)(long int)job_chain.pfunc(job_chain.pdata);
1295     }
1296     else {
1297       iterr = (PetscErrorCode)(long int)job_chain.pfunc(job_chain.pdata[ThreadId]);
1298     }
1299     if(iterr!=0) {
1300       ithreaderr = 1;
1301     }
1302     if(PetscThreadGo) {
1303       /* reset job, get ready for more */
1304       if(PeeOn==PETSC_FALSE) {
1305         /* check your subordinate, wait for him to be ready
1306          how do you know for a fact that your subordinate has actually started? */
1307         ierr = pthread_mutex_lock(job_chain.mutexarray[SubWorker]);
1308         while(*(job_chain.arrThreadReady[SubWorker])==PETSC_FALSE||*(job_chain.arrThreadStarted[SubWorker])==PETSC_FALSE) {
1309           /* upon entry, automically releases the lock and blocks
1310            upon return, has the lock */
1311           ierr = pthread_cond_wait(job_chain.cond1array[SubWorker],job_chain.mutexarray[SubWorker]);
1312         }
1313         ierr = pthread_mutex_unlock(job_chain.mutexarray[SubWorker]);
1314         /* your subordinate is now ready */
1315       }
1316       ierr = pthread_mutex_lock(job_chain.mutexarray[ThreadId]);
1317       *(job_chain.arrThreadReady[ThreadId]) = PETSC_TRUE;
1318       if(ThreadId==0) {
1319 	job_chain.eJobStat = JobCompleted; /* foreman: last thread to complete, guaranteed! */
1320         /* root thread (foreman) signals 'main' */
1321         ierr = pthread_cond_signal(&main_cond);
1322       }
1323       else {
1324         /* signal your boss before you go to sleep */
1325         ierr = pthread_cond_signal(job_chain.cond1array[ThreadId]);
1326       }
1327     }
1328   }
1329   return NULL;
1330 }
1331 
1332 #undef __FUNCT__
1333 #define __FUNCT__ "PetscThreadInitialize_Chain"
1334 void* PetscThreadInitialize_Chain(PetscInt N) {
1335   PetscInt i,ierr;
1336   int status;
1337 
1338   if(PetscUseThreadPool) {
1339     size_t Val1 = (size_t)CACHE_LINE_SIZE;
1340     size_t Val2 = (size_t)PetscMaxThreads*CACHE_LINE_SIZE;
1341     arrmutex = (char*)memalign(Val1,Val2);
1342     arrcond1 = (char*)memalign(Val1,Val2);
1343     arrcond2 = (char*)memalign(Val1,Val2);
1344     arrstart = (char*)memalign(Val1,Val2);
1345     arrready = (char*)memalign(Val1,Val2);
1346     job_chain.mutexarray       = (pthread_mutex_t**)malloc(PetscMaxThreads*sizeof(pthread_mutex_t*));
1347     job_chain.cond1array       = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*));
1348     job_chain.cond2array       = (pthread_cond_t**)malloc(PetscMaxThreads*sizeof(pthread_cond_t*));
1349     job_chain.arrThreadStarted = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*));
1350     job_chain.arrThreadReady   = (PetscBool**)malloc(PetscMaxThreads*sizeof(PetscBool*));
1351     /* initialize job structure */
1352     for(i=0; i<PetscMaxThreads; i++) {
1353       job_chain.mutexarray[i]        = (pthread_mutex_t*)(arrmutex+CACHE_LINE_SIZE*i);
1354       job_chain.cond1array[i]        = (pthread_cond_t*)(arrcond1+CACHE_LINE_SIZE*i);
1355       job_chain.cond2array[i]        = (pthread_cond_t*)(arrcond2+CACHE_LINE_SIZE*i);
1356       job_chain.arrThreadStarted[i]  = (PetscBool*)(arrstart+CACHE_LINE_SIZE*i);
1357       job_chain.arrThreadReady[i]    = (PetscBool*)(arrready+CACHE_LINE_SIZE*i);
1358     }
1359     for(i=0; i<PetscMaxThreads; i++) {
1360       ierr = pthread_mutex_init(job_chain.mutexarray[i],NULL);
1361       ierr = pthread_cond_init(job_chain.cond1array[i],NULL);
1362       ierr = pthread_cond_init(job_chain.cond2array[i],NULL);
1363       *(job_chain.arrThreadStarted[i])  = PETSC_FALSE;
1364       *(job_chain.arrThreadReady[i])    = PETSC_FALSE;
1365     }
1366     job_chain.pfunc = NULL;
1367     job_chain.pdata = (void**)malloc(N*sizeof(void*));
1368     job_chain.startJob = PETSC_FALSE;
1369     job_chain.eJobStat = JobInitiated;
1370     pVal = (int*)malloc(N*sizeof(int));
1371     /* allocate memory in the heap for the thread structure */
1372     PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t));
1373     /* create threads */
1374     for(i=0; i<N; i++) {
1375       pVal[i] = i;
1376       status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]);
1377       /* should check error */
1378     }
1379   }
1380   else {
1381   }
1382   return NULL;
1383 }
1384 
1385 
1386 #undef __FUNCT__
1387 #define __FUNCT__ "PetscThreadFinalize_Chain"
1388 PetscErrorCode PetscThreadFinalize_Chain() {
1389   int i,ierr;
1390   void* jstatus;
1391 
1392   PetscFunctionBegin;
1393 
1394   MainJob(FuncFinish,NULL,PetscMaxThreads);  /* set up job and broadcast work */
1395   /* join the threads */
1396   for(i=0; i<PetscMaxThreads; i++) {
1397     ierr = pthread_join(PetscThreadPoint[i],&jstatus);
1398     /* should check error */
1399   }
1400   free(PetscThreadPoint);
1401   free(arrmutex);
1402   free(arrcond1);
1403   free(arrcond2);
1404   free(arrstart);
1405   free(arrready);
1406   free(job_chain.pdata);
1407   free(pVal);
1408 
1409   PetscFunctionReturn(0);
1410 }
1411 
1412 #undef __FUNCT__
1413 #define __FUNCT__ "MainWait_Chain"
1414 void MainWait_Chain() {
1415   int ierr;
1416   ierr = pthread_mutex_lock(job_chain.mutexarray[0]);
1417   while(job_chain.eJobStat<JobCompleted||job_chain.startJob==PETSC_TRUE) {
1418     ierr = pthread_cond_wait(&main_cond,job_chain.mutexarray[0]);
1419   }
1420   ierr = pthread_mutex_unlock(job_chain.mutexarray[0]);
1421 }
1422 
1423 #undef __FUNCT__
1424 #define __FUNCT__ "MainJob_Chain"
1425 PetscErrorCode MainJob_Chain(void* (*pFunc)(void*),void** data,PetscInt n) {
1426   int i,ierr;
1427   PetscErrorCode ijoberr = 0;
1428 
1429   MainWait();
1430   job_chain.pfunc = pFunc;
1431   job_chain.pdata = data;
1432   job_chain.startJob = PETSC_TRUE;
1433   for(i=0; i<PetscMaxThreads; i++) {
1434     *(job_chain.arrThreadStarted[i]) = PETSC_FALSE;
1435   }
1436   job_chain.eJobStat = JobInitiated;
1437   ierr = pthread_cond_signal(job_chain.cond2array[0]);
1438   if(pFunc!=FuncFinish) {
1439     MainWait(); /* why wait after? guarantees that job gets done before proceeding with result collection (if any) */
1440   }
1441 
1442   if(ithreaderr) {
1443     ijoberr = ithreaderr;
1444   }
1445   return ijoberr;
1446 }
1447 /****  ****/
1448 
1449 #if defined(PETSC_HAVE_PTHREAD_BARRIER)
1450 /**** True Thread Functions ****/
1451 void* PetscThreadFunc_True(void* arg) {
1452   int icorr,ierr,iVal;
1453   int* pId = (int*)arg;
1454   int ThreadId = *pId;
1455   PetscErrorCode iterr;
1456   cpu_set_t mset;
1457   //printf("Thread %d In True Pool Thread Function\n",ThreadId);
1458   icorr = ThreadCoreAffinity[ThreadId];
1459   CPU_ZERO(&mset);
1460   CPU_SET(icorr,&mset);
1461   sched_setaffinity(0,sizeof(cpu_set_t),&mset);
1462 
1463   ierr = pthread_mutex_lock(&job_true.mutex);
1464   job_true.iNumReadyThreads++;
1465   if(job_true.iNumReadyThreads==PetscMaxThreads) {
1466     ierr = pthread_cond_signal(&main_cond);
1467   }
1468   /*the while loop needs to have an exit
1469     the 'main' thread can terminate all the threads by performing a broadcast
1470    and calling FuncFinish */
1471   while(PetscThreadGo) {
1472     /*need to check the condition to ensure we don't have to wait
1473       waiting when you don't have to causes problems
1474      also need to wait if another thread sneaks in and messes with the predicate */
1475     while(job_true.startJob==PETSC_FALSE&&job_true.iNumJobThreads==0) {
1476       /* upon entry, automically releases the lock and blocks
1477        upon return, has the lock */
1478       //printf("Thread %d Going to Sleep!\n",ThreadId);
1479       ierr = pthread_cond_wait(&job_true.cond,&job_true.mutex);
1480     }
1481     job_true.startJob = PETSC_FALSE;
1482     job_true.iNumJobThreads--;
1483     job_true.iNumReadyThreads--;
1484     iVal = PetscMaxThreads-job_true.iNumReadyThreads-1;
1485     pthread_mutex_unlock(&job_true.mutex);
1486     if(job_true.pdata==NULL) {
1487       iterr = (PetscErrorCode)(long int)job_true.pfunc(job_true.pdata);
1488     }
1489     else {
1490       iterr = (PetscErrorCode)(long int)job_true.pfunc(job_true.pdata[iVal]);
1491     }
1492     if(iterr!=0) {
1493       ithreaderr = 1;
1494     }
1495     //printf("Thread %d Finished Job\n",ThreadId);
1496     /* the barrier is necessary BECAUSE: look at job_true.iNumReadyThreads
1497       what happens if a thread finishes before they all start? BAD!
1498      what happens if a thread finishes before any else start? BAD! */
1499     pthread_barrier_wait(job_true.pbarr); /* ensures all threads are finished */
1500     /* reset job */
1501     if(PetscThreadGo) {
1502       pthread_mutex_lock(&job_true.mutex);
1503       job_true.iNumReadyThreads++;
1504       if(job_true.iNumReadyThreads==PetscMaxThreads) {
1505 	/* signal the 'main' thread that the job is done! (only done once) */
1506 	ierr = pthread_cond_signal(&main_cond);
1507       }
1508     }
1509   }
1510   return NULL;
1511 }
1512 
1513 #undef __FUNCT__
1514 #define __FUNCT__ "PetscThreadInitialize_True"
1515 void* PetscThreadInitialize_True(PetscInt N) {
1516   PetscInt i;
1517   int status;
1518 
1519   pVal = (int*)malloc(N*sizeof(int));
1520   /* allocate memory in the heap for the thread structure */
1521   PetscThreadPoint = (pthread_t*)malloc(N*sizeof(pthread_t));
1522   BarrPoint = (pthread_barrier_t*)malloc((N+1)*sizeof(pthread_barrier_t)); /* BarrPoint[0] makes no sense, don't use it! */
1523   job_true.pdata = (void**)malloc(N*sizeof(void*));
1524   for(i=0; i<N; i++) {
1525     pVal[i] = i;
1526     status = pthread_create(&PetscThreadPoint[i],NULL,PetscThreadFunc,&pVal[i]);
1527     /* error check to ensure proper thread creation */
1528     status = pthread_barrier_init(&BarrPoint[i+1],NULL,i+1);
1529     /* should check error */
1530   }
1531   //printf("Finished True Thread Pool Initialization\n");
1532   return NULL;
1533 }
1534 
1535 
1536 #undef __FUNCT__
1537 #define __FUNCT__ "PetscThreadFinalize_True"
1538 PetscErrorCode PetscThreadFinalize_True() {
1539   int i,ierr;
1540   void* jstatus;
1541 
1542   PetscFunctionBegin;
1543 
1544   MainJob(FuncFinish,NULL,PetscMaxThreads);  /* set up job and broadcast work */
1545   /* join the threads */
1546   for(i=0; i<PetscMaxThreads; i++) {
1547     ierr = pthread_join(PetscThreadPoint[i],&jstatus);
1548   }
1549   free(BarrPoint);
1550   free(PetscThreadPoint);
1551 
1552   PetscFunctionReturn(0);
1553 }
1554 
1555 #undef __FUNCT__
1556 #define __FUNCT__ "MainWait_True"
1557 void MainWait_True() {
1558   int ierr;
1559   ierr = pthread_mutex_lock(&job_true.mutex);
1560   while(job_true.iNumReadyThreads<PetscMaxThreads||job_true.startJob==PETSC_TRUE) {
1561     ierr = pthread_cond_wait(&main_cond,&job_true.mutex);
1562   }
1563   ierr = pthread_mutex_unlock(&job_true.mutex);
1564 }
1565 
1566 #undef __FUNCT__
1567 #define __FUNCT__ "MainJob_True"
1568 PetscErrorCode MainJob_True(void* (*pFunc)(void*),void** data,PetscInt n) {
1569   int ierr;
1570   PetscErrorCode ijoberr = 0;
1571 
1572   MainWait();
1573   job_true.pfunc = pFunc;
1574   job_true.pdata = data;
1575   job_true.pbarr = &BarrPoint[n];
1576   job_true.iNumJobThreads = n;
1577   job_true.startJob = PETSC_TRUE;
1578   ierr = pthread_cond_broadcast(&job_true.cond);
1579   if(pFunc!=FuncFinish) {
1580     MainWait(); /* why wait after? guarantees that job gets done */
1581   }
1582 
1583   if(ithreaderr) {
1584     ijoberr = ithreaderr;
1585   }
1586   return ijoberr;
1587 }
1588 /**** NO THREAD POOL FUNCTION ****/
1589 #undef __FUNCT__
1590 #define __FUNCT__ "MainJob_Spawn"
1591 PetscErrorCode MainJob_Spawn(void* (*pFunc)(void*),void** data,PetscInt n) {
1592   PetscErrorCode ijoberr = 0;
1593 
1594   pthread_t* apThread = (pthread_t*)malloc(n*sizeof(pthread_t));
1595   PetscThreadPoint = apThread; /* point to same place */
1596   PetscThreadRun(MPI_COMM_WORLD,pFunc,n,apThread,data);
1597   PetscThreadStop(MPI_COMM_WORLD,n,apThread); /* ensures that all threads are finished with the job */
1598   free(apThread);
1599 
1600   return ijoberr;
1601 }
1602 /****  ****/
1603 #endif
1604 
1605 void* FuncFinish(void* arg) {
1606   PetscThreadGo = PETSC_FALSE;
1607   return(0);
1608 }
1609 
1610 #endif
1611