00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #ifndef lint
00042 static const char RCSparallel[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/libbu/parallel.c,v 14.22 2006/09/03 15:14:07 lbutler Exp $ (ARL)";
00043 #endif
00044
00045 #include "common.h"
00046
00047
00048
00049 #include <stdio.h>
00050 #include <ctype.h>
00051 #include <math.h>
00052 #ifdef HAVE_SIGNAL_H
00053 # include <signal.h>
00054 #endif
00055 #ifdef HAVE_STRING_H
00056 # include <string.h>
00057 #else
00058 # include <strings.h>
00059 #endif
00060 #include "machine.h"
00061 #include "bu.h"
00062
00063 #ifdef linux
00064 # include <sys/time.h>
00065 # include <sys/types.h>
00066 # include <sys/resource.h>
00067 # ifdef HAVE_SYS_WAIT_H
00068 # include <sys/wait.h>
00069 # endif
00070 # include <sys/stat.h>
00071 # include <sys/sysinfo.h>
00072 #endif
00073
00074 #ifdef __FreeBSD__
00075 # include <sys/types.h>
00076 # include <sys/time.h>
00077 # include <sys/resource.h>
00078 # ifdef HAVE_SYS_WAIT_H
00079 # include <sys/wait.h>
00080 # endif
00081 # include <sys/stat.h>
00082 #endif
00083
00084 #ifdef __APPLE__
00085 # include <sys/types.h>
00086 # include <sys/time.h>
00087 # include <sys/resource.h>
00088 # ifdef HAVE_SYS_WAIT_H
00089 # include <sys/wait.h>
00090 # endif
00091 # include <sys/stat.h>
00092 # include <sys/param.h>
00093 # include <sys/sysctl.h>
00094 #endif
00095
00096 #ifdef __sp3__
00097 # include <sys/types.h>
00098 # include <sys/sysconfig.h>
00099 # include <sys/var.h>
00100 #endif
00101
00102 #ifdef CRAY
00103 # include <sys/category.h>
00104 # include <sys/resource.h>
00105 # include <sys/types.h>
00106 # ifdef CRAY1
00107 # include <sys/machd.h>
00108 # endif
00109 #endif
00110
00111 #ifdef CRAY2
00112 # undef MAXINT
00113 # include <sys/param.h>
00114 #endif
00115
00116 #ifdef HEP
00117 # include <synch.h>
00118 # undef stderr
00119 # define stderr stdout
00120 #endif
00121
00122 #if defined(alliant) && !defined(i860)
00123
00124 # include <cncall.h>
00125 #endif
00126
00127 #if (defined(sgi) && defined(mips)) || (defined(__sgi) && defined(__mips))
00128
00129 # define SGI_4D 1
00130 # define _SGI_SOURCE 1
00131 # define _BSD_TYPES 1
00132 #endif
00133
00134 #ifdef HAVE_SYS_TYPES_H
00135 # include <sys/types.h>
00136 #endif
00137 #ifdef HAVE_ULOCKS_H
00138 # include <ulocks.h>
00139 #endif
00140 #ifdef HAVE_SYS_SYSMP_H
00141 # include <sys/sysmp.h>
00142 #endif
00143 #ifdef HAVE_MALLOC_H
00144 # include <malloc.h>
00145 #endif
00146
00147 #ifdef HAVE_SYS_WAIT_H
00148 # include <sys/wait.h>
00149 #endif
00150
00151 #ifdef HAVE_SCHED_H
00152 # include <sched.h>
00153 #else
00154 # ifdef HAVE_SYS_SCHED_H
00155 # include <sys/sched.h>
00156 # endif
00157 #endif
00158 #if defined(IRIX64) && IRIX64 >= 64
00159 static struct sched_param bu_param;
00160 #endif
00161
00162 #ifdef ardent
00163 # include <thread.h>
00164 #endif
00165
00166 #if defined(n16)
00167 # include <parallel.h>
00168 # include <sys/sysadmin.h>
00169 #endif
00170
00171
00172
00173
00174 #if defined(SUNOS) && SUNOS >= 52
00175 # include <sys/unistd.h>
00176 # include <thread.h>
00177 # include <synch.h>
00178 # define rt_thread_t thread_t
00179 #endif
00180
00181
00182
00183
00184 #ifdef HAVE_UNISTD_H
00185 # include <unistd.h>
00186 #else
00187 # ifdef HAVE_SYS_UNISTD_H
00188 # include <sys/unistd.h>
00189 # endif
00190 #endif
00191 #ifdef HAVE_PTHREAD_H
00192 # include <pthread.h>
00193 # define rt_thread_t pthread_t
00194 #endif
00195
00196 #ifdef CRAY
00197 struct taskcontrol {
00198 int tsk_len;
00199 int tsk_id;
00200 int tsk_value;
00201 } bu_taskcontrol[MAX_PSW];
00202 #endif
00203
00204
00205
00206
00207
00208
00209
00210
00211 void
00212 bu_nice_set(int newnice)
00213 {
00214 #ifdef _WIN32
00215 if (bu_debug)
00216 bu_log("bu_nice_set() Priority NOT changed\n");
00217
00218 return;
00219
00220 #else
00221 int opri, npri;
00222
00223 # ifdef BSD
00224 # ifndef PRIO_PROCESS
00225 # define PRIO_PROCESS 0
00226 # endif
00227 opri = getpriority( PRIO_PROCESS, 0 );
00228 setpriority( PRIO_PROCESS, 0, newnice );
00229 npri = getpriority( PRIO_PROCESS, 0 );
00230
00231 # else
00232 int bias, chg;
00233
00234
00235
00236
00237 bias = 0;
00238 opri = nice(0) - bias;
00239 chg = newnice - opri;
00240 (void)nice(chg);
00241 npri = nice(0) - bias;
00242 if( npri != newnice ) bu_log("bu_nice_set() SysV error: wanted nice %d! check bias=%d\n", newnice, bias );
00243 # endif
00244
00245 if( bu_debug ) bu_log("bu_nice_set() Priority changed from %d to %d\n", opri, npri);
00246
00247 #endif
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257 int
00258 bu_cpulimit_get(void)
00259 {
00260 #ifdef CRAY
00261 long old;
00262 extern long limit();
00263
00264 if( (old = limit( C_PROC, 0, L_CPU, -1 )) < 0 ) {
00265 perror("bu_cpulimit_get(): CPU limit(get)");
00266 }
00267 if( old <= 0 )
00268 return(999999);
00269 return( (old + HZ - 1) / HZ );
00270 #else
00271 return(-1);
00272 #endif
00273 }
00274
00275
00276
00277
00278
00279
00280
00281 void
00282 bu_cpulimit_set(int sec)
00283 {
00284 #ifdef CRAY
00285 long old;
00286 long new;
00287 long newtick;
00288 extern long limit();
00289
00290 old = bu_cpulimit_get();
00291 new = old + sec;
00292 if( new <= 0 || new > 999999 )
00293 new = 999999;
00294 newtick = new * HZ;
00295 if( limit( C_PROC, 0, L_CPU, newtick ) < 0 ) {
00296 perror("bu_cpulimit_set: CPU limit(set)");
00297 }
00298 bu_log("Cray CPU limit changed from %d to %d seconds\n",
00299 old, newtick/HZ );
00300
00301
00302 if( limit( C_PROC, 0, L_MEM, 0 ) < 0 ) {
00303
00304 perror("bu_cpulimit_set: MEM limit(set)");
00305 }
00306 #endif
00307 if (sec < 0) sec = 0;
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 int
00319 bu_avail_cpus(void)
00320 {
00321 int ncpu = -1;
00322
00323
00324 #if defined(_SC_NPROCESSORS_ONLN)
00325
00326 ncpu = sysconf(_SC_NPROCESSORS_ONLN);
00327 if (ncpu < 0) {
00328 perror("Unable to get the number of available CPUs");
00329 ncpu = 1;
00330 }
00331 goto DONE_NCPU;
00332 #elif defined(_SC_NPROC_ONLN)
00333 ncpu = sysconf(_SC_NPROC_ONLN);
00334 if (ncpu < 0) {
00335 perror("Unable to get the number of available CPUs");
00336 ncpu = 1;
00337 }
00338 goto DONE_NCPU;
00339 #elif defined(_SC_CRAY_NCPU)
00340
00341 ncpu = sysconf(_SC_CRAY_NCPU);
00342 if (ncpu < 0) {
00343 perror("Unable to get the number of available CPUs");
00344 ncpu = 1;
00345 }
00346 goto DONE_NCPU;
00347 #endif
00348
00349
00350 #ifdef SGI_4D
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 # ifdef HAVE_SYSMP
00362 ncpu = sysmp(MP_NPROCS);
00363 # elif defined(HAVE_PRCTL)
00364 ncpu = (int)prctl(PR_MAXPPROCS);
00365 # endif
00366 goto DONE_NCPU;
00367 #endif
00368
00369
00370 #ifdef alliant
00371 {
00372 long memsize, ipnum, cenum, detnum, attnum;
00373
00374 # if !defined(i860)
00375
00376 lib_syscfg( &memsize, &ipnum, &cenum, &detnum, &attnum );
00377 # else
00378
00379 attnum = 28;
00380 # endif
00381 ncpu = attnum;
00382 goto DONE_NCPU;
00383 }
00384 #endif
00385
00386
00387 #if defined(__sp3__)
00388 {
00389 int status;
00390 int cmd;
00391 int parmlen;
00392 struct var p;
00393
00394 cmd = SYS_GETPARMS;
00395 parmlen = sizeof(struct var);
00396 if ( sysconfig(cmd, &p, parmlen) != 0 ) {
00397 bu_bomb("bu_parallel(): sysconfig error for sp3");
00398 }
00399 ncpu = p.v_ncpus;
00400 goto DONE_NCPU;
00401 }
00402 #endif
00403
00404
00405 #if defined(n16)
00406 if( (ncpu = sysadmin( SADMIN_NUMCPUS, 0 )) < 0 )
00407 perror("sysadmin");
00408 goto DONE_NCPU;
00409 #endif
00410
00411
00412 #ifdef __FreeBSD__
00413 {
00414 int maxproc;
00415 size_t len;
00416 len = 4;
00417 if (sysctlbyname("hw.ncpu", &maxproc, &len, NULL, 0) == -1) {
00418 ncpu = 1;
00419 perror("sysctlbyname");
00420 } else {
00421 ncpu = maxproc;
00422 }
00423 goto DONE_NCPU;
00424 }
00425 #endif
00426
00427
00428 #if defined(__ppc__)
00429 {
00430 int mib[2], maxproc;
00431 size_t len;
00432
00433 mib[0] = CTL_HW;
00434 mib[1] = HW_NCPU;
00435 len = sizeof(maxproc);
00436 if (sysctl(mib, 2, &maxproc, &len, NULL, 0) == -1) {
00437 ncpu = 1;
00438 perror("sysctl");
00439 } else {
00440 ncpu = maxproc;
00441 }
00442 goto DONE_NCPU;
00443 }
00444 #endif
00445
00446
00447 #if defined(HAVE_GET_NPROCS)
00448 ncpu = get_nprocs();
00449 goto DONE_NCPU;
00450 #endif
00451
00452
00453 #if defined(linux) && 0
00454 {
00455
00456
00457
00458
00459
00460
00461
00462 # define CPUINFO_FILE "/proc/cpuinfo"
00463 FILE *fp;
00464 char buf[128];
00465
00466 ncpu = 0;
00467
00468 fp = fopen (CPUINFO_FILE,"r");
00469
00470 if (fp == NULL) {
00471 ncpu = 1;
00472 perror (CPUINFO_FILE);
00473 } else {
00474 while (fgets (buf, 80, fp) != NULL) {
00475 if (strncmp (buf, "processor",9) == 0) {
00476 ++ ncpu;
00477 }
00478 }
00479 fclose (fp);
00480
00481 if (ncpu <= 0) {
00482 ncpu = 1;
00483 }
00484 }
00485 goto DONE_NCPU;
00486 }
00487 #endif
00488
00489 #if defined(_WIN32)
00490
00491 {
00492 SYSTEM_INFO sysinfo;
00493
00494 GetSystemInfo(&sysinfo);
00495 ncpu = (int)sysinfo.dwNumberOfProcessors;
00496 goto DONE_NCPU;
00497 }
00498 #endif
00499
00500 DONE_NCPU: ;
00501
00502
00503 #if defined(HAVE_PTHREAD_H)
00504
00505 if (ncpu < 0) {
00506 ncpu = 2;
00507 }
00508 #endif
00509
00510 if (bu_debug & BU_DEBUG_PARALLEL) {
00511
00512 fprintf( stderr, "bu_avail_cpus: counted %d cpus.\n", ncpu);
00513 }
00514
00515 if (ncpu > 0) {
00516 return ncpu;
00517 }
00518
00519 return( DEFAULT_PSW );
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533 fastf_t
00534 bu_get_load_average(void)
00535 {
00536 double load = -1.0;
00537 #ifndef _WIN32
00538 FILE *fp;
00539
00540 fp = popen("PATH=/bin:/usr/bin:/usr/ucb:/usr/bsd; export PATH; uptime|sed -e 's/.*average: //' -e 's/,.*//' ", "r");
00541 if( !fp )
00542 return -1.0;
00543
00544 fscanf( fp, "%lf", &load );
00545 fclose(fp);
00546
00547 while( wait(NULL) != -1 ) ;
00548 #endif
00549 return load;
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 #ifndef _WIN32
00564 # define PUBLIC_CPUS1 "/var/tmp/public_cpus"
00565 # define PUBLIC_CPUS2 "/usr/tmp/public_cpus"
00566 #endif
00567 int
00568 bu_get_public_cpus(void)
00569 {
00570 int avail_cpus = bu_avail_cpus();
00571 #ifndef _WIN32
00572 int public_cpus = 1;
00573 FILE *fp;
00574
00575 if( (fp = fopen(PUBLIC_CPUS1, "r")) != NULL ||
00576 (fp = fopen(PUBLIC_CPUS2, "r")) != NULL
00577 ) {
00578 (void)fscanf( fp, "%d", &public_cpus );
00579 fclose(fp);
00580 if( public_cpus < 0 ) public_cpus = avail_cpus + public_cpus;
00581 if( public_cpus > avail_cpus ) public_cpus = avail_cpus;
00582 return public_cpus;
00583 }
00584
00585 (void)unlink(PUBLIC_CPUS1);
00586 (void)unlink(PUBLIC_CPUS2);
00587 if( (fp = fopen(PUBLIC_CPUS1, "w")) != NULL ||
00588 (fp = fopen(PUBLIC_CPUS2, "w")) != NULL
00589 ) {
00590 fprintf(fp, "%d\n", avail_cpus);
00591 fclose(fp);
00592 (void)chmod(PUBLIC_CPUS1, 0666);
00593 (void)chmod(PUBLIC_CPUS2, 0666);
00594 }
00595 #endif
00596 return avail_cpus;
00597 }
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609 int
00610 bu_set_realtime(void)
00611 {
00612 # if defined(IRIX64) && IRIX64 >= 64
00613 {
00614 int policy;
00615
00616 if( (policy = sched_getscheduler(0)) >= 0 ) {
00617 if( policy == SCHED_RR || policy == SCHED_FIFO )
00618 return 1;
00619 }
00620
00621 sched_getparam( 0, &bu_param );
00622
00623 if ( sched_setscheduler( 0,
00624 SCHED_RR,
00625 &bu_param
00626 ) >= 0 ) {
00627 return 1;
00628 }
00629
00630 }
00631 # endif
00632 return 0;
00633 }
00634
00635
00636
00637 #if defined(unix) || defined(__unix)
00638
00639
00640
00641 # define CHECK_PIDS 1
00642 #endif
00643
00644 #if defined(PARALLEL)
00645
00646
00647 # ifdef SGI_4D
00648
00649
00650
00651
00652 static int
00653 bu_worker_tbl_not_empty(tbl)
00654 int tbl[MAX_PSW];
00655 {
00656 register int i;
00657 register int children=0;
00658
00659 for (i=1 ; i < MAX_PSW ; ++i)
00660 if (tbl[i]) children++;
00661
00662 return(children);
00663 }
00664
00665
00666
00667
00668 static void
00669 bu_kill_workers(tbl)
00670 int tbl[MAX_PSW];
00671 {
00672 register int i;
00673
00674 for (i=1 ; i < MAX_PSW ; ++i) {
00675 if ( tbl[i] ) {
00676 if( kill(tbl[i], 9) ) {
00677 perror("bu_kill_workers(): SIGKILL to child process");
00678 }
00679 else {
00680 bu_log("bu_kill_workers(): child pid %d killed\n", tbl[i]);
00681 }
00682 }
00683 }
00684
00685 bzero( (char *)tbl, sizeof(tbl) );
00686 }
00687 # endif
00688
00689 extern int bu_pid_of_initiating_thread;
00690
00691 static int bu_nthreads_started = 0;
00692 static int bu_nthreads_finished = 0;
00693 static void (*bu_parallel_func) BU_ARGS((int,genptr_t));
00694 static genptr_t bu_parallel_arg;
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 static void
00712 bu_parallel_interface(void)
00713 {
00714 register int cpu;
00715
00716 #if 0
00717 #ifdef HAVE_PTHREAD_H
00718 {
00719 pthread_t pt;
00720 pt = pthread_self();
00721 fprintf(stderr,"bu_parallel_interface, Thread ID = 0x%x\n", (unsigned int)pt);
00722 }
00723 #endif
00724 #endif
00725 bu_semaphore_acquire( BU_SEM_SYSCALL );
00726 cpu = bu_nthreads_started++;
00727 bu_semaphore_release( BU_SEM_SYSCALL );
00728
00729 (*bu_parallel_func)(cpu, bu_parallel_arg);
00730
00731 bu_semaphore_acquire( BU_SEM_SYSCALL );
00732 bu_nthreads_finished++;
00733 bu_semaphore_release( BU_SEM_SYSCALL );
00734
00735 # if defined(SGI_4D) || defined(IRIX)
00736
00737
00738
00739
00740
00741
00742 if(cpu) _exit(0);
00743 # endif
00744 }
00745 #endif
00746
00747 #ifdef SGI_4D
00748
00749
00750
00751
00752
00753 void
00754 bu_pr_FILE(title, fp)
00755 char *title;
00756 FILE *fp;
00757 {
00758 bu_log("FILE structure '%s', at x%x:\n", title, fp );
00759 bu_log(" _cnt = x%x\n", fp->_cnt);
00760 bu_log(" _ptr = x%x\n", fp->_ptr);
00761 bu_log(" _base = x%x\n", fp->_base);
00762 bu_log(" _file = x%x\n", fp->_file);
00763 bu_printb(" _flag ", fp->_flag & 0xFF,
00764 "\010\010_IORW\7_100\6_IOERR\5_IOEOF\4_IOMYBUF\3_004\2_IOWRT\1_IOREAD" );
00765 bu_log("\n");
00766 }
00767 #endif
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788 void
00789 bu_parallel( func, ncpu, arg )
00790 void (*func) BU_ARGS((int, genptr_t));
00791 int ncpu;
00792 genptr_t arg;
00793 {
00794 #if defined(PARALLEL)
00795 int avail_cpus;
00796
00797 # if defined(alliant) && !defined(i860) && !__STDC__
00798 register int d7;
00799 register int d6 = ncpu;
00800 # endif
00801 int x;
00802
00803 # if defined(SGI_4D) || defined(CRAY)
00804 int new;
00805 # endif
00806
00807 # ifdef sgi
00808 long stdin_pos;
00809 FILE stdin_save;
00810 int worker_pid_tbl[MAX_PSW];
00811 # endif
00812
00813
00814
00815
00816 # if defined(SUNOS) && SUNOS >= 52
00817 static int concurrency = 0;
00818 # endif
00819 # if (defined(SUNOS) && SUNOS >= 52) || defined(HAVE_PTHREAD_H)
00820 int nthreadc;
00821 int nthreade;
00822 rt_thread_t thread;
00823 rt_thread_t thread_tbl[MAX_PSW];
00824 int i;
00825 # endif
00826
00827 # ifdef sgi
00828 bzero(worker_pid_tbl, sizeof(worker_pid_tbl) );
00829 # endif
00830
00831 if( bu_debug & BU_DEBUG_PARALLEL )
00832 bu_log("bu_parallel(0x%lx, %d, x%lx)\n", (long)func, ncpu, (long)arg );
00833
00834 if( bu_pid_of_initiating_thread )
00835 bu_bomb("bu_parallel() called from within parallel section\n");
00836
00837 bu_pid_of_initiating_thread = getpid();
00838
00839 if (ncpu > MAX_PSW) {
00840 bu_log("WARNING: bu_parallel() ncpu(%d) > MAX_PSW(%d), adjusting ncpu\n", ncpu, MAX_PSW);
00841 ncpu = MAX_PSW;
00842 }
00843 bu_nthreads_started = 0;
00844 bu_nthreads_finished = 0;
00845 bu_parallel_func = func;
00846 bu_parallel_arg = arg;
00847 avail_cpus = bu_avail_cpus();
00848 if( ncpu > avail_cpus ) {
00849 bu_log( "%d cpus requested, but only %d available\n", ncpu, avail_cpus );
00850 ncpu = avail_cpus;
00851 }
00852
00853
00854 # ifdef HEP
00855 bu_nthreads_started = 1;
00856 bu_nthreads_finished = 1;
00857 for( x=1; x<ncpu; x++ ) {
00858
00859 Dcreate( bu_parallel_interface );
00860 }
00861 (*func)(0,arg);
00862 # endif
00863
00864 # ifdef CRAY
00865 # if 0
00866
00867 new = 0;
00868 TSKTUNE( "DBRELEAS", &new );
00869 # endif
00870
00871 bu_nthreads_started = 1;
00872 bu_nthreads_finished = 1;
00873
00874 for( x=1; x<ncpu; x++ ) {
00875 bu_taskcontrol[x].tsk_len = 3;
00876 bu_taskcontrol[x].tsk_value = x;
00877 TSKSTART( &bu_taskcontrol[x], bu_parallel_interface );
00878 }
00879 (*func)(0,arg);
00880
00881
00882 for( x=1; x<ncpu; x++ ) {
00883 TSKWAIT( &bu_taskcontrol[x] );
00884 }
00885
00886 # endif
00887
00888 # if defined(alliant) && !defined(i860)
00889 # if defined(__STDC__)
00890 # undef __STDC__
00891 # define __STDC__ 2
00892
00893
00894 concurrent_call(CNCALL_COUNT|CNCALL_NO_QUIT, bu_parallel_interface, ncpu);
00895
00896 # else
00897 {
00898 asm(" movl d6,d0");
00899 asm(" subql #1,d0");
00900 asm(" cstart d0");
00901 asm("super_loop:");
00902 bu_parallel_interface();
00903 asm(" crepeat super_loop");
00904 }
00905 # endif
00906 # endif
00907
00908 # if defined(alliant) && defined(i860)
00909 #pragma loop cncall
00910 for( x=0; x<ncpu; x++) {
00911 bu_parallel_interface();
00912 }
00913 # endif
00914
00915 # if defined(convex) || defined(__convex__)
00916
00917 for( x=0; x<ncpu; x++ ) {
00918 bu_parallel_interface();
00919 }
00920 # endif
00921
00922 # ifdef ardent
00923
00924 parstack( bu_parallel_interface, 1024*1024, ncpu );
00925 # endif
00926
00927 # ifdef SGI_4D
00928 stdin_pos = ftell(stdin);
00929 stdin_save = *(stdin);
00930 bu_nthreads_started = 1;
00931 bu_nthreads_finished = 1;
00932
00933
00934
00935 for( x = 1; x < ncpu; x++) {
00936
00937
00938
00939
00940
00941 # if defined(IRIX) && IRIX <= 4
00942
00943 new = sproc( bu_parallel_interface, PR_SALL, 0 );
00944 # else
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 new = sprocsp( (void (*)(void *, size_t))bu_parallel_interface,
00955 PR_SALL, 0, NULL,
00956 # if defined(IRIX64)
00957 64*1024*1024 - 32*1024
00958 # else
00959 4*1024*1024 - 32*1024
00960 # endif
00961 );
00962 # endif
00963 if( new < 0 ) {
00964 perror("sproc");
00965 bu_log("ERROR bu_parallel(): sproc(x%x, x%x, )=%d failed on processor %d\n",
00966 bu_parallel_interface, PR_SALL,
00967 new, x );
00968 bu_log("sbrk(0)=x%x\n", sbrk(0) );
00969 bu_bomb("bu_parallel() failure");
00970 } else {
00971 worker_pid_tbl[x] = new;
00972 }
00973
00974 }
00975 (*func)(0,arg);
00976 {
00977 int pid;
00978 int pstat;
00979 int children;
00980
00981
00982
00983
00984 while ( children=bu_worker_tbl_not_empty(worker_pid_tbl) ) {
00985 pstat = 0;
00986 if ( (pid = wait(&pstat)) < 0) {
00987 perror("bu_parallel() wait()");
00988 bu_kill_workers(worker_pid_tbl);
00989 bu_bomb("parallelism error");
00990 } else if (pid == 0) {
00991 bu_log("bu_parallel() wait() == 0 with %d children remaining\n", children);
00992 bu_kill_workers(worker_pid_tbl);
00993 bu_bomb("Missing worker");
00994 } else {
00995 if( (pstat & 0xFF) != 0 ) {
00996 bu_log("***ERROR: bu_parallel() worker %d exited with status x%x!\n", pid, pstat);
00997
00998 # ifdef IRIX
00999 if (WIFEXITED(pstat))
01000 bu_log ("Child terminated normally with status %d 0x%0x\n",
01001 WEXITSTATUS(pstat));
01002
01003 if (WIFSIGNALED(pstat)) {
01004 bu_log("child terminated on signal %d %0x\n", WTERMSIG(pstat));
01005 if (pstat & 0200)
01006 bu_log("core dumped\n");
01007 else
01008 bu_log("No core dump\n");
01009 }
01010 if (WIFSTOPPED(pstat))
01011 bu_log("child is stopped on signal %d 0x%x\n", WSTOPSIG(pstat));
01012
01013 if ( (pstat & 0177777) == 0177777 )
01014 bu_log("child has continued\n");
01015
01016 # endif
01017 bu_kill_workers(worker_pid_tbl);
01018 bu_bomb("A worker blew out");
01019 }
01020
01021 for (x=1 ; x < ncpu ; x++)
01022 if (worker_pid_tbl[x] == pid) {
01023 worker_pid_tbl[x] = 0;
01024 break;
01025 }
01026
01027 if (x >= ncpu) {
01028 bu_log("WARNING: bu_parallel(): wait() returned non-child process, pid %d\n", pid);
01029 }
01030 }
01031 }
01032 }
01033 if( ftell(stdin) != stdin_pos ) {
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043 bu_log("\nWarning: stdin file pointer has been corrupted by SGI multi-processor bug!\n");
01044 if( bu_debug & BU_DEBUG_PARALLEL ) {
01045 bu_log("Original position was x%x, now position is x%x!\n", stdin_pos, ftell(stdin) );
01046 bu_pr_FILE("saved stdin", &stdin_save);
01047 bu_pr_FILE("current stdin", stdin);
01048 }
01049 fseek(stdin, stdin_pos, SEEK_SET);
01050 if( ftell(stdin) != stdin_pos ) {
01051 bu_log("WARNING: fseek() did not recover proper position.\n");
01052 } else {
01053 bu_log("It was fixed by fseek()\n");
01054 }
01055 }
01056 # endif
01057
01058 # if defined(n16)
01059
01060
01061 if( task_init( 8*1024*1024, ncpu, bu_parallel_interface, 128*1024, 0 ) < 0 )
01062 perror("bu_parallel()/task_init()");
01063 # endif
01064
01065
01066
01067
01068 # if defined(SUNOS) && SUNOS >= 52
01069
01070 thread = 0;
01071 nthreadc = 0;
01072
01073
01074 if (ncpu > concurrency) {
01075 if (thr_setconcurrency(ncpu)) {
01076 fprintf(stderr, "ERROR parallel.c/bu_parallel(): thr_setconcurrency(%d) failed\n",
01077 ncpu);
01078 bu_log("ERROR parallel.c/bu_parallel(): thr_setconcurrency(%d) failed\n",
01079 ncpu);
01080
01081 } else {
01082 concurrency = ncpu;
01083 }
01084 }
01085
01086
01087 for (x = 0; x < ncpu; x++) {
01088
01089 if (thr_create(0, 0, (void *(*)(void *))bu_parallel_interface, 0, 0, &thread)) {
01090 fprintf(stderr, "ERROR parallel.c/bu_parallel(): thr_create(0x0, 0x0, 0x%x, 0x0, 0, 0x%x) failed on processor %d\n",
01091 bu_parallel_interface, &thread, x);
01092 bu_log("ERROR parallel.c/bu_parallel(): thr_create(0x0, 0x0, 0x%x, 0x0, 0, 0x%x) failed on processor %d\n",
01093 bu_parallel_interface, &thread, x);
01094
01095 } else {
01096 if( bu_debug & BU_DEBUG_PARALLEL )
01097 bu_log("bu_parallel(): created thread: (thread: 0x%x) (loop:%d) (nthreadc:%d)\n",
01098 thread, x, nthreadc);
01099
01100 thread_tbl[nthreadc] = thread;
01101 nthreadc++;
01102 }
01103 }
01104
01105 if( bu_debug & BU_DEBUG_PARALLEL )
01106 for (i = 0; i < nthreadc; i++)
01107 bu_log("bu_parallel(): thread_tbl[%d] = 0x%x\n",
01108 i, thread_tbl[i]);
01109
01110
01111
01112
01113
01114
01115
01116 thread = 0;
01117 nthreade = 0;
01118 for (x = 0; x < nthreadc; x++) {
01119 if( bu_debug & BU_DEBUG_PARALLEL )
01120 bu_log("bu_parallel(): waiting for thread to complete:\t(loop:%d) (nthreadc:%d) (nthreade:%d)\n",
01121 x, nthreadc, nthreade);
01122
01123 if (thr_join((rt_thread_t)0, &thread, NULL)) {
01124
01125 fprintf(stderr, "thr_join()");
01126 }
01127
01128
01129 for (i = 0; i < nthreadc; i++) {
01130 if (thread_tbl[i] == thread) {
01131 thread_tbl[i] = (rt_thread_t)-1;
01132 nthreade++;
01133 break;
01134 }
01135 }
01136
01137 if ((thread_tbl[i] != (rt_thread_t)-1) && i < nthreadc) {
01138 bu_log("bu_parallel(): unknown thread %d completed.\n",
01139 thread);
01140 }
01141
01142 if( bu_debug & BU_DEBUG_PARALLEL )
01143 bu_log("bu_parallel(): thread completed: (thread: %d)\t(loop:%d) (nthreadc:%d) (nthreade:%d)\n",
01144 thread, x, nthreadc, nthreade);
01145 }
01146
01147 if( bu_debug & BU_DEBUG_PARALLEL )
01148 bu_log("bu_parallel(): %d threads created. %d threads exited.\n",
01149 nthreadc, nthreade);
01150 # endif
01151
01152 # if defined(HAVE_PTHREAD_H) && !defined(sgi)
01153
01154 thread = 0;
01155 nthreadc = 0;
01156
01157
01158
01159
01160 for (x = 0; x < ncpu; x++) {
01161 pthread_attr_t attrs;
01162 pthread_attr_init(&attrs);
01163 pthread_attr_setstacksize(&attrs,10*1024*1024);
01164
01165 if (pthread_create(&thread, &attrs,
01166 (void *(*)(void *))bu_parallel_interface, NULL)) {
01167 fprintf(stderr, "ERROR parallel.c/bu_parallel(): thr_create(0x0, 0x0, 0x%lx, 0x0, 0, 0x%lx) failed on processor %d\n",
01168 (unsigned long int)bu_parallel_interface, (unsigned long int)&thread, x);
01169 bu_log("ERROR parallel.c/bu_parallel(): thr_create(0x0, 0x0, 0x%x, 0x0, 0, 0x%x) failed on processor %d\n",
01170 bu_parallel_interface, &thread, x);
01171
01172 } else {
01173 if( bu_debug & BU_DEBUG_PARALLEL ) {
01174 bu_log("bu_parallel(): created thread: (thread: %d) (loop:%d) (nthreadc:%d)\n",
01175 thread, x, nthreadc);
01176 }
01177
01178 thread_tbl[nthreadc] = thread;
01179 nthreadc++;
01180 }
01181 }
01182
01183
01184 if( bu_debug & BU_DEBUG_PARALLEL ) {
01185 for (i = 0; i < nthreadc; i++) {
01186 bu_log("bu_parallel(): thread_tbl[%d] = %d\n",
01187 i, thread_tbl[i]);
01188 }
01189 # if defined(HAVE_RAISE) && defined(SIGINFO)
01190
01191 raise(SIGINFO);
01192 # endif
01193 }
01194
01195
01196
01197
01198
01199 thread = 0;
01200 nthreade = 0;
01201 for (x = 0; x < nthreadc; x++) {
01202 int ret;
01203
01204 if( bu_debug & BU_DEBUG_PARALLEL )
01205 bu_log("bu_parallel(): waiting for thread x%x to complete:\t(loop:%d) (nthreadc:%d) (nthreade:%d)\n",
01206 thread_tbl[x], x, nthreadc, nthreade);
01207
01208 if ( (ret = pthread_join(thread_tbl[x], NULL)) != 0) {
01209
01210 fprintf(stderr, "pthread_join(thread_tbl[%d]=0x%x) ret=%d\n", x, (unsigned int)thread_tbl[x], ret);
01211 }
01212 nthreade++;
01213 thread_tbl[x] = (rt_thread_t)-1;
01214
01215 if( bu_debug & BU_DEBUG_PARALLEL )
01216 bu_log("bu_parallel(): thread completed: (thread: %d)\t(loop:%d) (nthreadc:%d) (nthreade:%d)\n",
01217 thread, x, nthreadc, nthreade);
01218 }
01219
01220 if( bu_debug & BU_DEBUG_PARALLEL )
01221 bu_log("bu_parallel(): %d threads created. %d threads exited.\n",
01222 nthreadc, nthreade);
01223
01224 # endif
01225
01226
01227
01228
01229
01230
01231 if( bu_nthreads_finished != bu_nthreads_started ) {
01232 bu_log("*** ERROR bu_parallel(%d): %d workers did not finish!\n\n",
01233 ncpu, ncpu - bu_nthreads_finished);
01234 }
01235 if( bu_nthreads_started != ncpu ) {
01236 bu_log("bu_parallel() NOTICE: only %d workers started, expected %d\n",
01237 bu_nthreads_started, ncpu );
01238 }
01239
01240 if( bu_debug & BU_DEBUG_PARALLEL )
01241 bu_log("bu_parallel(%d) complete, now serial\n", ncpu);
01242
01243 # ifdef CHECK_PIDS
01244
01245
01246
01247
01248
01249
01250 if( bu_pid_of_initiating_thread != (x=getpid()) ) {
01251 bu_log("WARNING: bu_parallel(): PID of initiating thread changed from %d to %d, open file table may be botched!\n",
01252 bu_pid_of_initiating_thread, x );
01253 }
01254 # endif
01255 bu_pid_of_initiating_thread = 0;
01256 #else
01257 bu_log("bu_parallel( x%lx, %d., x%lx ): Not compiled for PARALLEL machine, running single-threaded\n", (long)func, ncpu, (long)arg );
01258
01259 (*func)(0,arg);
01260 #endif
01261
01262 return;
01263 }
01264
01265 #if defined(sgi) && !defined(mips)
01266
01267 long float
01268 hypot(a,b)
01269 double a,b;
01270 {
01271 return(sqrt(a*a+b*b));
01272 }
01273 #endif
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285