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 #ifndef lint
00040 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/many.c,v 14.12 2006/09/16 02:04:25 lbutler Exp $ (ARL)";
00041 #endif
00042
00043 #include "common.h"
00044
00045
00046
00047 #include <stdio.h>
00048 #include <math.h>
00049 #include "machine.h"
00050 #include "bu.h"
00051 #include "vmath.h"
00052 #include "bn.h"
00053 #include "raytrace.h"
00054
00055
00056 struct rt_many_internal {
00057 long magic;
00058 long cur_index;
00059 long max_index;
00060 const struct application *proto_ap;
00061 struct resource *resources;
00062 int (*callback) BU_ARGS((struct application *, int index));
00063 int stop_worker;
00064 int sem_chunk;
00065 };
00066 #define RT_MANY_INTERNAL_MAGIC 0x526d6970
00067 #define RT_CK_RMI(_p) BU_CKMAG(_p, RT_MANY_INTERNAL_MAGIC, "rt_many_internal")
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 void
00079 rt_shoot_many_rays_worker(int cpu, genptr_t arg)
00080 {
00081 LOCAL struct application app;
00082 struct rt_many_internal *rmip = (struct rt_many_internal *)arg;
00083
00084 if( cpu >= MAX_PSW ) {
00085 bu_log("rt_shoot_many_rays_worker() cpu %d > MAX_PSW %d, array overrun\n", cpu, MAX_PSW);
00086 rt_bomb("rt_shoot_many_rays_worker() cpu > MAX_PSW, array overrun\n");
00087 }
00088
00089 RT_CK_RMI(rmip);
00090 RT_CK_RESOURCE( &rmip->resources[cpu] );
00091 RT_CK_APPLICATION( rmip->proto_ap );
00092
00093 app = *rmip->proto_ap;
00094 app.a_resource = &rmip->resources[cpu];
00095
00096 while(1) {
00097 register long index;
00098 register long lim;
00099
00100 if( rmip->stop_worker ) break;
00101
00102 bu_semaphore_acquire( RT_SEM_WORKER );
00103 index = rmip->cur_index;
00104 rmip->cur_index += rmip->sem_chunk;
00105 bu_semaphore_release( RT_SEM_WORKER );
00106
00107 lim = index + rmip->sem_chunk;
00108 for( ; index < lim; index++ ) {
00109 if( index >= rmip->max_index ) return;
00110
00111
00112
00113
00114
00115
00116 app.a_x = index;
00117
00118
00119 if( (*rmip->callback)( &app, index ) < 0 ) {
00120 rmip->stop_worker = 1;
00121 break;
00122 }
00123
00124 (void)rt_shootray( &app );
00125 }
00126 }
00127 }
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 void
00164 rt_shoot_many_rays(const struct application *proto_ap, int (*callback) (struct application *, int), int ncpus, long int nrays, struct resource *resources)
00165
00166
00167
00168
00169
00170 {
00171 struct rt_many_internal rmi;
00172 int i;
00173
00174 RT_CK_APPLICATION(proto_ap);
00175 for( i=0; i < ncpus; i++ ) {
00176 RT_CK_RESOURCE( &resources[i] );
00177 }
00178 rmi.resources = resources;
00179
00180 rmi.magic = RT_MANY_INTERNAL_MAGIC;
00181 rmi.stop_worker = 0;
00182 rmi.cur_index = 0;
00183 rmi.max_index = nrays;
00184 rmi.proto_ap = proto_ap;
00185 rmi.callback = callback;
00186 rmi.sem_chunk = ncpus;
00187
00188 if( !rt_g.rtg_parallel || ncpus <= 1 ) {
00189
00190 rt_shoot_many_rays_worker( 0, (genptr_t)&rmi );
00191 } else {
00192 bu_parallel( rt_shoot_many_rays_worker, ncpus, (genptr_t)&rmi );
00193 }
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204