1 #define PETSC_DLL 2 /* 3 Code to handle PETSc starting up in debuggers,etc. 4 */ 5 6 #include "petsc.h" /*I "petsc.h" I*/ 7 #include <signal.h> 8 #include "petscsys.h" /*I "petscsys.h" I*/ 9 #if defined(PETSC_HAVE_UNISTD_H) 10 #include <unistd.h> 11 #endif 12 #if defined(PETSC_HAVE_STDLIB_H) 13 #include <stdlib.h> 14 #endif 15 #include "petscfix.h" 16 17 /* 18 These are the debugger and display used if the debugger is started up 19 */ 20 static char Debugger[PETSC_MAX_PATH_LEN]; 21 static char DebugTerminal[PETSC_MAX_PATH_LEN]; 22 static PetscTruth Xterm = PETSC_TRUE; 23 24 #undef __FUNCT__ 25 #define __FUNCT__ "PetscSetDebugTerminal" 26 /*@C 27 PetscSetDebugTerminal - Sets the terminal to use (instead of xterm) for debugging. 28 29 Not Collective 30 31 Input Parameters: 32 + terminal - name of terminal and any flags required to execute a program. 33 For example "xterm -e", "urxvt -e". 34 35 Options Database Keys: 36 -debug_terminal terminal - use this terminal instead of xterm 37 38 Level: developer 39 40 Notes: 41 You can start the debugger for all processes in the same GNU screen session. 42 43 mpirun -n 4 ./myapp -start_in_debugger -debug_terminal "screen -X -S debug screen" 44 45 will open 4 windows in the session named "debug". 46 47 Fortran Note: 48 This routine is not supported in Fortran. 49 50 Concepts: debugger^setting 51 52 .seealso: PetscSetDebugger() 53 @*/ 54 PetscErrorCode PETSC_DLLEXPORT PetscSetDebugTerminal(const char terminal[]) 55 { 56 PetscErrorCode ierr; 57 58 PetscFunctionBegin; 59 ierr = PetscStrcpy(DebugTerminal,terminal);CHKERRQ(ierr); 60 PetscFunctionReturn(0); 61 } 62 63 #undef __FUNCT__ 64 #define __FUNCT__ "PetscSetDebugger" 65 /*@C 66 PetscSetDebugger - Sets options associated with the debugger. 67 68 Not Collective 69 70 Input Parameters: 71 + debugger - name of debugger, which should be in your path, 72 usually "dbx", "gdb", "idb", "xxgdb", "kdgb" or "ddd". Also, HP-UX 73 supports "xdb", and IBM rs6000 supports "xldb". 74 75 - xterm - flag to indicate debugger window, set to either 1 (to indicate 76 debugger should be started in a new xterm) or 0 (to start debugger 77 in initial window (the option 0 makes no sense when using more 78 than one processor.) 79 80 Level: developer 81 82 Fortran Note: 83 This routine is not supported in Fortran. 84 85 Concepts: debugger^setting 86 87 .seealso: PetscAttachDebugger(), PetscAttachDebuggerErrorHandler() 88 @*/ 89 PetscErrorCode PETSC_DLLEXPORT PetscSetDebugger(const char debugger[],PetscTruth xterm) 90 { 91 PetscErrorCode ierr; 92 93 PetscFunctionBegin; 94 if (debugger) { 95 ierr = PetscStrcpy(Debugger,debugger);CHKERRQ(ierr); 96 } 97 Xterm = xterm; 98 99 PetscFunctionReturn(0); 100 } 101 102 #undef __FUNCT__ 103 #define __FUNCT__ "PetscSetDefaultDebugger" 104 /*@ 105 PetscSetDefaultDebugger - Causes PETSc to use its default 106 debugger. 107 108 Not collective 109 110 Level: advanced 111 112 .seealso: PetscSetDebugger(), PetscSetDebuggerFromString() 113 @*/ 114 PetscErrorCode PETSC_DLLEXPORT PetscSetDefaultDebugger(void) 115 { 116 PetscErrorCode ierr; 117 118 PetscFunctionBegin; 119 #if defined(PETSC_USE_DBX_DEBUGGER) 120 ierr = PetscSetDebugger("dbx",PETSC_TRUE);CHKERRQ(ierr); 121 #elif defined(PETSC_USE_XDB_DEBUGGER) 122 ierr = PetscSetDebugger("xdb",PETSC_TRUE);CHKERRQ(ierr); 123 #elif defined(PETSC_USE_IDB_DEBUGGER) 124 ierr = PetscSetDebugger("idb",PETSC_TRUE);CHKERRQ(ierr); 125 #else /* Default is gdb */ 126 ierr = PetscSetDebugger("gdb",PETSC_TRUE);CHKERRQ(ierr); 127 #endif 128 ierr = PetscSetDebugTerminal("xterm -e");CHKERRQ(ierr); 129 PetscFunctionReturn(0); 130 } 131 132 #undef __FUNCT__ 133 #define __FUNCT__ "PetscCheckDebugger_Private" 134 static PetscErrorCode PetscCheckDebugger_Private(const char defaultDbg[], const char string[], const char *debugger[]) 135 { 136 PetscTruth exists; 137 char *f; 138 PetscErrorCode ierr; 139 140 PetscFunctionBegin; 141 ierr = PetscStrstr(string, defaultDbg, &f);CHKERRQ(ierr); 142 if (f) { 143 ierr = PetscTestFile(string, 'x', &exists);CHKERRQ(ierr); 144 if (exists) { 145 *debugger = string; 146 } else { 147 *debugger = defaultDbg; 148 } 149 } 150 PetscFunctionReturn(0); 151 } 152 153 #undef __FUNCT__ 154 #define __FUNCT__ "PetscSetDebuggerFromString" 155 /*@C 156 PetscSetDebuggerFromString - Set the complete path for the 157 debugger for PETSc to use. 158 159 Not collective 160 161 Level: advanced 162 163 .seealso: PetscSetDebugger(), PetscSetDefaultDebugger() 164 @*/ 165 PetscErrorCode PETSC_DLLEXPORT PetscSetDebuggerFromString(char *string) 166 { 167 const char *debugger = PETSC_NULL; 168 PetscTruth xterm = PETSC_TRUE; 169 char *f; 170 PetscErrorCode ierr; 171 172 PetscFunctionBegin; 173 ierr = PetscStrstr(string, "noxterm", &f);CHKERRQ(ierr); 174 if (f) xterm = PETSC_FALSE; 175 ierr = PetscStrstr(string, "ddd", &f);CHKERRQ(ierr); 176 if (f) xterm = PETSC_FALSE; 177 ierr = PetscCheckDebugger_Private("xdb", string, &debugger);CHKERRQ(ierr); 178 ierr = PetscCheckDebugger_Private("dbx", string, &debugger);CHKERRQ(ierr); 179 ierr = PetscCheckDebugger_Private("xldb", string, &debugger);CHKERRQ(ierr); 180 ierr = PetscCheckDebugger_Private("gdb", string, &debugger);CHKERRQ(ierr); 181 ierr = PetscCheckDebugger_Private("idb", string, &debugger);CHKERRQ(ierr); 182 ierr = PetscCheckDebugger_Private("xxgdb", string, &debugger);CHKERRQ(ierr); 183 ierr = PetscCheckDebugger_Private("ddd", string, &debugger);CHKERRQ(ierr); 184 ierr = PetscCheckDebugger_Private("kdbg", string, &debugger);CHKERRQ(ierr); 185 ierr = PetscCheckDebugger_Private("ups", string, &debugger);CHKERRQ(ierr); 186 ierr = PetscCheckDebugger_Private("workshop", string, &debugger);CHKERRQ(ierr); 187 ierr = PetscCheckDebugger_Private("pgdbg", string, &debugger);CHKERRQ(ierr); 188 ierr = PetscCheckDebugger_Private("pathdb", string, &debugger);CHKERRQ(ierr); 189 190 ierr = PetscSetDebugger(debugger, xterm);CHKERRQ(ierr); 191 PetscFunctionReturn(0); 192 } 193 194 195 #undef __FUNCT__ 196 #define __FUNCT__ "PetscAttachDebugger" 197 /*@ 198 PetscAttachDebugger - Attaches the debugger to the running process. 199 200 Not Collective 201 202 Level: advanced 203 204 Concepts: debugger^starting from program 205 206 .seealso: PetscSetDebugger() 207 @*/ 208 PetscErrorCode PETSC_DLLEXPORT PetscAttachDebugger(void) 209 { 210 #if !defined(PETSC_CANNOT_START_DEBUGGER) 211 int child=0; 212 PetscInt sleeptime=0; 213 PetscErrorCode ierr; 214 char program[PETSC_MAX_PATH_LEN],display[256],hostname[64]; 215 #endif 216 217 PetscFunctionBegin; 218 219 #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK) 220 (*PetscErrorPrintf)("System cannot start debugger\n"); 221 (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n"); 222 (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n"); 223 MPI_Finalize(); 224 exit(0); 225 #else 226 ierr = PetscGetDisplay(display,128);CHKERRQ(ierr); 227 ierr = PetscGetProgramName(program,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 228 if (ierr) { 229 (*PetscErrorPrintf)("Cannot determine program name\n"); 230 PetscFunctionReturn(1); 231 } 232 if (!program[0]) { 233 (*PetscErrorPrintf)("Cannot determine program name\n"); 234 PetscFunctionReturn(1); 235 } 236 child = (int)fork(); 237 if (child < 0) { 238 (*PetscErrorPrintf)("Error in fork() attaching debugger\n"); 239 PetscFunctionReturn(1); 240 } 241 242 /* 243 Swap role the parent and child. This is (I think) so that control c typed 244 in the debugger goes to the correct process. 245 */ 246 if (child) { child = 0; } 247 else { child = (int)getppid(); } 248 249 if (child) { /* I am the parent, will run the debugger */ 250 const char *args[10]; 251 char pid[10]; 252 PetscInt j,jj; 253 PetscTruth isdbx,isidb,isxldb,isxxgdb,isups,isxdb,isworkshop,isddd,iskdbg; 254 255 ierr = PetscGetHostName(hostname,64);CHKERRQ(ierr); 256 /* 257 We need to send a continue signal to the "child" process on the 258 alpha, otherwise it just stays off forever 259 */ 260 #if defined (PETSC_NEED_KILL_FOR_DEBUGGER) 261 kill(child,SIGCONT); 262 #endif 263 sprintf(pid,"%d",child); 264 265 ierr = PetscStrcmp(Debugger,"xxgdb",&isxxgdb);CHKERRQ(ierr); 266 ierr = PetscStrcmp(Debugger,"ddd",&isddd);CHKERRQ(ierr); 267 ierr = PetscStrcmp(Debugger,"kdbg",&iskdbg);CHKERRQ(ierr); 268 ierr = PetscStrcmp(Debugger,"ups",&isups);CHKERRQ(ierr); 269 ierr = PetscStrcmp(Debugger,"xldb",&isxldb);CHKERRQ(ierr); 270 ierr = PetscStrcmp(Debugger,"xdb",&isxdb);CHKERRQ(ierr); 271 ierr = PetscStrcmp(Debugger,"dbx",&isdbx);CHKERRQ(ierr); 272 ierr = PetscStrcmp(Debugger,"idb",&isidb);CHKERRQ(ierr); 273 ierr = PetscStrcmp(Debugger,"workshop",&isworkshop);CHKERRQ(ierr); 274 275 if (isxxgdb || isups || isddd ) { 276 args[1] = program; args[2] = pid; args[3] = "-display"; 277 args[0] = Debugger; args[4] = display; args[5] = 0; 278 (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname); 279 if (execvp(args[0],(char**)args) < 0) { 280 perror("Unable to start debugger"); 281 exit(0); 282 } 283 } else if (iskdbg) { 284 args[1] = "-p"; args[2] = pid; args[3] = program; args[4] = "-display"; 285 args[0] = Debugger; args[5] = display; args[6] = 0; 286 (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[3],pid,hostname); 287 if (execvp(args[0],(char**)args) < 0) { 288 perror("Unable to start debugger"); 289 exit(0); 290 } 291 } else if (isxldb) { 292 args[1] = "-a"; args[2] = pid; args[3] = program; args[4] = "-display"; 293 args[0] = Debugger; args[5] = display; args[6] = 0; 294 (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname); 295 if (execvp(args[0],(char**)args) < 0) { 296 perror("Unable to start debugger"); 297 exit(0); 298 } 299 } else if (isworkshop) { 300 args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-"; 301 args[0] = Debugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = 0; 302 (*PetscErrorPrintf)("PETSC: Attaching %s to %s on %s\n",args[0],pid,hostname); 303 if (execvp(args[0],(char**)args) < 0) { 304 perror("Unable to start debugger"); 305 exit(0); 306 } 307 } else { 308 j = 0; 309 if (Xterm) { 310 PetscTruth cmp; 311 char *tmp,*tmp1; 312 ierr = PetscStrncmp(DebugTerminal,"screen",6,&cmp);CHKERRQ(ierr); 313 if (cmp) display[0] = 0; /* when using screen, we never pass -display */ 314 args[j++] = tmp = DebugTerminal; 315 if (display[0]) { 316 args[j++] = "-display"; args[j++] = display; 317 } 318 while (*tmp) { 319 ierr = PetscStrchr(tmp,' ',&tmp1);CHKERRQ(ierr); 320 if (!tmp1) break; 321 *tmp1 = 0; 322 tmp = tmp1+1; 323 args[j++] = tmp; 324 } 325 } 326 args[j++] = Debugger; 327 jj = j; 328 args[j++] = program; args[j++] = pid; args[j++] = 0; 329 330 if (isidb) { 331 j = jj; 332 args[j++] = "-pid"; 333 args[j++] = pid; 334 args[j++] = "-gdb"; 335 args[j++] = program; 336 args[j++] = 0; 337 } 338 #if defined(PETSC_USE_P_FOR_DEBUGGER) 339 if (isdbx) { 340 j = jj; 341 args[j++] = "-p"; 342 args[j++] = pid; 343 args[j++] = program; 344 args[j++] = 0; 345 } 346 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 347 if (isxdb) { 348 j = jj; 349 args[j++] = "-l"; 350 args[j++] = "ALL"; 351 args[j++] = "-P"; 352 args[j++] = pid; 353 args[j++] = program; 354 args[j++] = 0; 355 } 356 #elif defined(PETSC_USE_A_FOR_DEBUGGER) 357 if (isdbx) { 358 j = jj; 359 args[j++] = "-a"; 360 args[j++] = pid; 361 args[j++] = 0; 362 } 363 #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 364 if (isdbx) { 365 j = jj; 366 args[j++] = "-pid"; 367 args[j++] = pid; 368 args[j++] = program; 369 args[j++] = 0; 370 } 371 #endif 372 if (Xterm) { 373 if (display[0]) { 374 (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n",Debugger,program,pid,display,hostname); 375 } else { 376 (*PetscErrorPrintf)("PETSC: Attaching %s to %s on pid %s on %s\n",Debugger,program,pid,hostname); 377 } 378 if (execvp(args[0],(char**)args) < 0) { 379 perror("Unable to start debugger in xterm"); 380 exit(0); 381 } 382 } else { 383 (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on %s\n",Debugger,program,pid,hostname); 384 if (execvp(args[0],(char**)args) < 0) { 385 perror("Unable to start debugger"); 386 exit(0); 387 } 388 } 389 } 390 } else { /* I am the child, continue with user code */ 391 sleeptime = 10; /* default to sleep waiting for debugger */ 392 ierr = PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);CHKERRQ(ierr); 393 if (sleeptime < 0) sleeptime = -sleeptime; 394 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP) 395 /* 396 HP cannot attach process to sleeping debugger, hence count instead 397 */ 398 { 399 PetscReal x = 1.0; 400 int i=10000000; 401 while (i--) x++ ; /* cannot attach to sleeper */ 402 } 403 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY) 404 /* 405 IBM sleep may return at anytime, hence must see if there is more time to sleep 406 */ 407 { 408 int left = sleeptime; 409 while (left > 0) {left = PetscSleep(left) - 1;} 410 } 411 #else 412 PetscSleep(sleeptime); 413 #endif 414 } 415 #endif 416 PetscFunctionReturn(0); 417 } 418 419 #undef __FUNCT__ 420 #define __FUNCT__ "PetscAttachDebuggerErrorHandler" 421 /*@C 422 PetscAttachDebuggerErrorHandler - Error handler that attaches 423 a debugger to a running process when an error is detected. 424 This routine is useful for examining variables, etc. 425 426 Not Collective 427 428 Input Parameters: 429 + line - the line number of the error (indicated by __LINE__) 430 . fun - function where error occured (indicated by __FUNCT__) 431 . file - the file in which the error was detected (indicated by __FILE__) 432 . dir - the directory of the file (indicated by __SDIR__) 433 . message - an error text string, usually just printed to the screen 434 . number - the generic error number 435 . p - the specific error number 436 - ctx - error handler context 437 438 Options Database Keys: 439 . -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates 440 debugger attachment 441 442 Level: developer 443 444 Notes: 445 By default the GNU debugger, gdb, is used. Alternatives are dbx and 446 xxgdb,xldb (on IBM rs6000), xdb (on HP-UX). 447 448 Most users need not directly employ this routine and the other error 449 handlers, but can instead use the simplified interface SETERR, which has 450 the calling sequence 451 $ SETERRQ(number,p,message) 452 453 Notes for experienced users: 454 Use PetscPushErrorHandler() to set the desired error handler. The 455 currently available PETSc error handlers are 456 $ PetscTraceBackErrorHandler() 457 $ PetscAttachDebuggerErrorHandler() 458 $ PetscAbortErrorHandler() 459 or you may write your own. 460 461 Concepts: debugger^error handler 462 Concepts: error handler^attach debugger 463 464 .seealso: PetscPushErrorHandler(), PetscTraceBackErrorHandler(), 465 PetscAbortErrorHandler() 466 @*/ 467 PetscErrorCode PETSC_DLLEXPORT PetscAttachDebuggerErrorHandler(int line,const char* fun,const char *file,const char* dir,int num,int p,const char* mess,void *ctx) 468 { 469 PetscErrorCode ierr; 470 471 PetscFunctionBegin; 472 if (!fun) fun = "User provided function"; 473 if (!dir) dir = " "; 474 if (!mess) mess = " "; 475 476 (*PetscErrorPrintf)("%s() line %d in %s%s %s\n",fun,line,dir,file,mess); 477 478 ierr = PetscAttachDebugger(); 479 if (ierr) { /* hopeless so get out */ 480 MPI_Finalize(); 481 exit(num); 482 } 483 PetscFunctionReturn(0); 484 } 485 486 #undef __FUNCT__ 487 #define __FUNCT__ "PetscStopForDebugger" 488 /*@C 489 PetscStopForDebugger - Prints a message to the screen indicating how to 490 attach to the process with the debugger and then waits for the 491 debugger to attach. 492 493 Not Collective 494 495 Level: advanced 496 497 Concepts: debugger^waiting for attachment 498 499 .seealso: PetscSetDebugger(), PetscAttachDebugger() 500 @*/ 501 PetscErrorCode PETSC_DLLEXPORT PetscStopForDebugger(void) 502 { 503 PetscErrorCode ierr; 504 PetscInt sleeptime=0; 505 int err; 506 #if !defined(PETSC_CANNOT_START_DEBUGGER) 507 int ppid; 508 PetscMPIInt rank; 509 char program[PETSC_MAX_PATH_LEN],hostname[256]; 510 PetscTruth isdbx,isxldb,isxxgdb,isddd,iskdbg,isups,isxdb; 511 #endif 512 513 PetscFunctionBegin; 514 #if defined(PETSC_CANNOT_START_DEBUGGER) 515 (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n"); 516 #else 517 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); 518 ierr = PetscGetHostName(hostname,256); 519 if (ierr) { 520 (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n"); 521 PetscFunctionReturn(0); 522 } 523 524 ierr = PetscGetProgramName(program,256); 525 if (ierr) { 526 (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"); 527 PetscFunctionReturn(0); 528 } 529 if (!program[0]) { 530 (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"); 531 PetscFunctionReturn(0); 532 } 533 534 ppid = getpid(); 535 536 ierr = PetscStrcmp(Debugger,"xxgdb",&isxxgdb);CHKERRQ(ierr); 537 ierr = PetscStrcmp(Debugger,"ddd",&isddd);CHKERRQ(ierr); 538 ierr = PetscStrcmp(Debugger,"kdbg",&iskdbg);CHKERRQ(ierr); 539 ierr = PetscStrcmp(Debugger,"ups",&isups);CHKERRQ(ierr); 540 ierr = PetscStrcmp(Debugger,"xldb",&isxldb);CHKERRQ(ierr); 541 ierr = PetscStrcmp(Debugger,"xdb",&isxdb);CHKERRQ(ierr); 542 ierr = PetscStrcmp(Debugger,"dbx",&isdbx);CHKERRQ(ierr); 543 544 if (isxxgdb || isups || isddd || iskdbg ) { 545 (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid); 546 } 547 #if defined(PETSC_USE_A_FOR_DEBUGGER) 548 else if (isxldb) { 549 (*PetscErrorPrintf)("{%d]%s>>%s -a %d %s\n",rank,hostname,Debugger,ppid,program); 550 } 551 #endif 552 #if defined(PETSC_USE_P_FOR_DEBUGGER) 553 else if (isdbx) { 554 (*PetscErrorPrintf)("[%d]%s>>%s -p %d %s\n",rank,hostname,Debugger,ppid,program); 555 } 556 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 557 else if (isxdb) { 558 (*PetscErrorPrintf)("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,Debugger,ppid,program); 559 } 560 #elif defined(PETSC_USE_A_FOR_DEBUGGER) 561 else if (isdbx) { 562 (*PetscErrorPrintf)("[%d]%s>>%s -a %d\n",rank,hostname,Debugger,ppid); 563 } 564 #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 565 else if (isdbx) { 566 (*PetscErrorPrintf)("[%d]%s>>%s -pid %d %s\n",rank,hostname,Debugger,ppid,program); 567 } 568 #else 569 else { 570 (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid); 571 } 572 #endif 573 #endif /* PETSC_CANNOT_START_DEBUGGER */ 574 575 err = fflush(stdout); 576 if (err) SETERRQ(PETSC_ERR_SYS,"fflush() failed on stdout"); 577 578 sleeptime = 25; /* default to sleep waiting for debugger */ 579 ierr = PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);CHKERRQ(ierr); 580 if (sleeptime < 0) sleeptime = -sleeptime; 581 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP) 582 /* 583 HP cannot attach process to sleeping debugger, hence count instead 584 */ 585 { 586 PetscReal x = 1.0; 587 int i=10000000; 588 while (i--) x++ ; /* cannot attach to sleeper */ 589 } 590 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY) 591 /* 592 IBM sleep may return at anytime, hence must see if there is more time to sleep 593 */ 594 { 595 int left = sleeptime; 596 while (left > 0) {left = sleep(left) - 1;} 597 } 598 #else 599 PetscSleep(sleeptime); 600 #endif 601 PetscFunctionReturn(0); 602 } 603 604 605 606