8feb516a82bc5a3043216563b79d0d896bc305a4
[ghc-hetmet.git] / ghc / rts / parallel / Parallel.c
1 /*
2   Time-stamp: <Sat Dec 04 1999 19:43:39 Stardate: [-30]3999.10 hwloidl>
3
4   Basic functions for use in either GranSim or GUM.
5 */
6
7 #if defined(GRAN) || defined(PAR)                              /* whole file */
8
9 //@menu
10 //* Includes::                  
11 //* Variables and constants::   
12 //* Writing to the log-file::   
13 //* Dumping routines::          
14 //@end menu
15
16 //@node Includes, Variables and constants
17 //@subsection Includes
18
19 #include "Rts.h"
20 #include "RtsFlags.h"
21 #include "RtsUtils.h"
22 #include "GranSimRts.h"
23 #include "ParallelRts.h"
24
25
26 //@node Variables and constants, Writing to the log-file, Includes
27 //@subsection Variables and constants
28
29 /* Where to write the log file */
30 FILE *gr_file = NULL;
31 char gr_filename[STATS_FILENAME_MAXLEN];
32
33 //@node Writing to the log-file, Dumping routines, Variables and constants
34 //@subsection Writing to the log-file
35 /*
36   Writing to the log-file
37
38   These routines dump event-based info to the main log-file.
39   The code for writing log files is shared between GranSim and GUM.
40 */
41
42 /* 
43  * If you're not using GNUC and you're on a 32-bit machine, you're 
44  * probably out of luck here.  However, since CONCURRENT currently
45  * requires GNUC, I'm not too worried about it.  --JSM
46  */
47
48 //@cindex init_gr_simulation
49 #if defined(GRAN)
50 void
51 init_gr_simulation(rts_argc, rts_argv, prog_argc, prog_argv)
52 char *prog_argv[], *rts_argv[];
53 int prog_argc, rts_argc;
54 {
55   nat i;
56   char *extension = RtsFlags.GranFlags.GranSimStats.Binary ? "gb" : "gr";
57
58   if (RtsFlags.GranFlags.GranSimStats.Global)
59     init_gr_stats();
60
61   /* init global constants for costs of basic operations */
62   gran_arith_cost = RtsFlags.GranFlags.Costs.arith_cost;
63   gran_branch_cost = RtsFlags.GranFlags.Costs.branch_cost;
64   gran_load_cost = RtsFlags.GranFlags.Costs.load_cost;
65   gran_store_cost = RtsFlags.GranFlags.Costs.store_cost;
66   gran_float_cost = RtsFlags.GranFlags.Costs.float_cost;
67
68   if (RtsFlags.GranFlags.GranSimStats.Suppressed)
69     return;
70
71   if (!RtsFlags.GranFlags.GranSimStats.Full) 
72     return;
73
74   sprintf(gr_filename, GR_FILENAME_FMT, prog_argv[0], extension);
75
76   if ((gr_file = fopen(gr_filename, "w")) == NULL) {
77     barf("Can't open granularity simulation report file %s\n", 
78          gr_filename);
79   }
80
81   setbuf(gr_file, NULL); // for debugging turn buffering off
82
83   /* write header with program name, options and setup to gr_file */
84   fputs("Granularity Simulation for ", gr_file);
85   for (i = 0; i < prog_argc; ++i) {
86     fputs(prog_argv[i], gr_file);
87     fputc(' ', gr_file);
88   }
89
90   if (rts_argc > 0) {
91     fputs("+RTS ", gr_file);
92     
93     for (i = 0; i < rts_argc; ++i) {
94       fputs(rts_argv[i], gr_file);
95       fputc(' ', gr_file);
96     }
97   }
98
99   fputs("\nStart time: ", gr_file);
100   fputs(time_str(), gr_file);               /* defined in RtsUtils.c */
101   fputc('\n', gr_file);
102     
103   fputs("\n\n--------------------\n\n", gr_file);
104
105   fputs("General Parameters:\n\n", gr_file);
106
107   if (RtsFlags.GranFlags.Light) 
108     fprintf(gr_file, "GrAnSim-Light\nPEs infinite, %s Scheduler, %sMigrate Threads %s, %s\n",
109             RtsFlags.GranFlags.DoFairSchedule?"Fair":"Unfair",
110             RtsFlags.GranFlags.DoThreadMigration?"":"Don't ",
111             RtsFlags.GranFlags.DoThreadMigration && RtsFlags.GranFlags.DoStealThreadsFirst?" Before Sparks":"",
112             RtsFlags.GranFlags.DoAsyncFetch ? "Asynchronous Fetch" :
113             "Block on Fetch");
114   else 
115     fprintf(gr_file, "PEs %u, %s Scheduler, %sMigrate Threads %s, %s\n",
116             RtsFlags.GranFlags.proc,RtsFlags.GranFlags.DoFairSchedule?"Fair":"Unfair",
117             RtsFlags.GranFlags.DoThreadMigration?"":"Don't ",
118             RtsFlags.GranFlags.DoThreadMigration && RtsFlags.GranFlags.DoStealThreadsFirst?" Before Sparks":"",
119             RtsFlags.GranFlags.DoAsyncFetch ? "Asynchronous Fetch" :
120             "Block on Fetch");
121   
122   if (RtsFlags.GranFlags.DoBulkFetching) 
123     if (RtsFlags.GranFlags.ThunksToPack)
124       fprintf(gr_file, "Bulk Fetching: Fetch %d Thunks in Each Packet (Packet Size = %d closures)\n",
125               RtsFlags.GranFlags.ThunksToPack, 
126               RtsFlags.GranFlags.packBufferSize);
127     else
128       fprintf(gr_file, "Bulk Fetching: Fetch as many closures as possible (Packet Size = %d closures)\n",
129               RtsFlags.GranFlags.packBufferSize);
130   else
131     fprintf(gr_file, "Incremental Fetching: Fetch Exactly One Closure in Each Packet\n");
132   
133   fprintf(gr_file, "Fetch Strategy(%u):If outstanding fetches %s\n",
134           RtsFlags.GranFlags.FetchStrategy,
135           RtsFlags.GranFlags.FetchStrategy==0 ?
136             " block (block-on-fetch)":
137           RtsFlags.GranFlags.FetchStrategy==1 ?
138             "only run runnable threads":
139           RtsFlags.GranFlags.FetchStrategy==2 ? 
140             "create threads only from local sparks":
141           RtsFlags.GranFlags.FetchStrategy==3 ? 
142             "create threads from local or global sparks":
143           RtsFlags.GranFlags.FetchStrategy==4 ?
144             "create sparks and steal threads if necessary":
145           "unknown");
146
147   if (RtsFlags.GranFlags.DoPrioritySparking)
148     fprintf(gr_file, "Priority Sparking (i.e. keep sparks ordered by priority)\n");
149
150   if (RtsFlags.GranFlags.DoPriorityScheduling)
151     fprintf(gr_file, "Priority Scheduling (i.e. keep threads ordered by priority)\n");
152
153   fprintf(gr_file, "Thread Creation Time %u, Thread Queue Time %u\n",
154           RtsFlags.GranFlags.Costs.threadcreatetime, 
155           RtsFlags.GranFlags.Costs.threadqueuetime);
156   fprintf(gr_file, "Thread DeSchedule Time %u, Thread Schedule Time %u\n",
157           RtsFlags.GranFlags.Costs.threaddescheduletime, 
158           RtsFlags.GranFlags.Costs.threadscheduletime);
159   fprintf(gr_file, "Thread Context-Switch Time %u\n",
160           RtsFlags.GranFlags.Costs.threadcontextswitchtime);
161   fputs("\n\n--------------------\n\n", gr_file);
162
163   fputs("Communication Metrics:\n\n", gr_file);
164   fprintf(gr_file,
165           "Latency %u (1st) %u (rest), Fetch %u, Notify %u (Global) %u (Local)\n",
166           RtsFlags.GranFlags.Costs.latency, 
167           RtsFlags.GranFlags.Costs.additional_latency, 
168           RtsFlags.GranFlags.Costs.fetchtime,
169           RtsFlags.GranFlags.Costs.gunblocktime, 
170           RtsFlags.GranFlags.Costs.lunblocktime);
171   fprintf(gr_file,
172           "Message Creation %u (+ %u after send), Message Read %u\n",
173           RtsFlags.GranFlags.Costs.mpacktime, 
174           RtsFlags.GranFlags.Costs.mtidytime, 
175           RtsFlags.GranFlags.Costs.munpacktime);
176   fputs("\n\n--------------------\n\n", gr_file);
177
178   fputs("Instruction Metrics:\n\n", gr_file);
179   fprintf(gr_file, "Arith %u, Branch %u, Load %u, Store %u, Float %u, Alloc %u\n",
180           RtsFlags.GranFlags.Costs.arith_cost, 
181           RtsFlags.GranFlags.Costs.branch_cost,
182           RtsFlags.GranFlags.Costs.load_cost, 
183           RtsFlags.GranFlags.Costs.store_cost, 
184           RtsFlags.GranFlags.Costs.float_cost, 
185           RtsFlags.GranFlags.Costs.heapalloc_cost);
186   fputs("\n\n++++++++++++++++++++\n\n", gr_file);
187
188 # if 0
189   /* binary log files are currently not supported */
190   if (RtsFlags.GranFlags.GranSimStats.Binary)
191     grputw(sizeof(rtsTime));
192 # endif
193
194   return (0);
195 }
196
197 #elif defined(PAR)
198
199 void
200 init_gr_simulation(rts_argc, rts_argv, prog_argc, prog_argv)
201 char *prog_argv[], *rts_argv[];
202 int prog_argc, rts_argc;
203 {
204   nat i;
205   char time_string[TIME_STR_LEN], node_str[NODE_STR_LEN];
206   char *extension = RtsFlags.ParFlags.ParStats.Binary ? "gb" : "gr";
207
208   sprintf(gr_filename, GR_FILENAME_FMT_GUM, prog_argv[0], thisPE, extension);
209
210   if (!RtsFlags.ParFlags.ParStats.Full) 
211     return;
212
213   if ((gr_file = fopen(gr_filename, "w")) == NULL)
214     barf("Can't open activity report file %s\n", gr_filename);
215
216   setbuf(gr_file, NULL); // for debugging turn buffering off
217
218   /* write header with program name, options and setup to gr_file */
219   for (i = 0; i < prog_argc; ++i) {
220     fputs(prog_argv[i], gr_file);
221     fputc(' ', gr_file);
222   }
223
224   if (rts_argc > 0) {
225     fputs("+RTS ", gr_file);
226     
227     for (i = 0; i < rts_argc; ++i) {
228       fputs(rts_argv[i], gr_file);
229       fputc(' ', gr_file);
230     }
231   }
232   fputc('\n', gr_file);
233
234   /* record the absolute start time to allow synchronisation of log-files */
235   fputs("Start-Time: ", gr_file);
236   fputs(time_str(), gr_file);
237   fputc('\n', gr_file);
238     
239   startTime = CURRENT_TIME;
240   ullong_format_string(CURRENT_TIME, time_string, rtsFalse/*no commas!*/);
241   fprintf(gr_file, "PE %2u [%s]: TIME\n", thisPE, time_string);
242
243   /*
244   IF_PAR_DEBUG(verbose,
245                belch("== Start-time: %ld (%s)",
246                      startTime, time_string));
247   */
248 # if 0
249     ngoq Dogh'q' vImuS
250
251     if (startTime > LL(1000000000)) {
252       fprintf(gr_file, "PE %2u [%lu%lu]: TIME\n", thisPE, 
253             (rtsTime) (startTime / LL(1000000000)),
254             (rtsTime) (startTime % LL(1000000000)));
255     } else {
256       fprintf(gr_file, "PE %2u [%lu]: TIME\n", thisPE, (TIME) startTime);
257     } 
258     /* binary log files are currently not supported */
259     if (RtsFlags.GranFlags.GranSimStats.Binary)
260         grputw(sizeof(rtsTime));
261 # endif
262
263     return;
264 }
265 #endif /* PAR */
266
267 //@cindex end_gr_simulation
268 #if defined(GRAN)
269 void
270 end_gr_simulation(void)
271 {
272    char time_string[TIME_STR_LEN];
273
274    ullong_format_string(CURRENT_TIME, time_string, rtsFalse/*no commas!*/);
275
276    if (RtsFlags.GranFlags.GranSimStats.Suppressed)
277      return;
278
279    /* Print event stats */
280    if (RtsFlags.GranFlags.GranSimStats.Global) {
281      nat i;
282    
283      fprintf(stderr,"Total yields: %d\n",
284              globalGranStats.tot_yields);
285
286      fprintf(stderr,"Total number of threads created: %d ; per PE:\n",
287              globalGranStats.tot_threads_created);
288      for (i=0; i<RtsFlags.GranFlags.proc; i++) {
289        fprintf(stderr,"  PE %d: %d\t", 
290                i, globalGranStats.threads_created_on_PE[i]);
291        if (i+1 % 4 == 0) fprintf(stderr,"\n");
292      }
293      if (RtsFlags.GranFlags.proc+1 % 4 != 0) fprintf(stderr,"\n");
294      fprintf(stderr,"Total number of threads migrated: %d\n",
295              globalGranStats.tot_TSOs_migrated);
296
297      fprintf(stderr,"Total number of sparks created: %d ; per PE:\n",
298              globalGranStats.tot_sparks_created);
299      for (i=0; i<RtsFlags.GranFlags.proc; i++) {
300        fprintf(stderr,"  PE %d: %d\t", 
301                i, globalGranStats.sparks_created_on_PE[i]);
302        if (i+1 % 4 == 0) fprintf(stderr,"\n");
303      }
304      if (RtsFlags.GranFlags.proc+1 % 4 != 0) fprintf(stderr,"\n");
305
306      fprintf(stderr,"Event statistics (number of events: %d):\n",
307              globalGranStats.noOfEvents);
308      for (i=0; i<=MAX_EVENT; i++) {
309        fprintf(stderr,"  %s (%d): \t%d \t%f%%\t%f%%\n",
310                event_names[i],i,globalGranStats.event_counts[i],
311                (float)(100*globalGranStats.event_counts[i])/(float)(globalGranStats.noOfEvents),
312                (i==ContinueThread ? 0.0 :
313                    (float)(100*(globalGranStats.event_counts[i])/(float)(globalGranStats.noOfEvents-globalGranStats.event_counts[ContinueThread])) ));
314      }
315      fprintf(stderr,"Randomized steals: %ld sparks, %ld threads \n \t(Sparks: #%u (avg ntimes=%f; avg fl=%f)\n\t(Threads: %ld)", 
316                      globalGranStats.rs_sp_count, 
317                      globalGranStats.rs_t_count, 
318                      globalGranStats.no_of_steals, 
319                      (float)globalGranStats.ntimes_total/(float)stg_max(globalGranStats.no_of_steals,1),
320                      (float)globalGranStats.fl_total/(float)stg_max(globalGranStats.no_of_steals,1),
321                      globalGranStats.no_of_migrates);
322      fprintf(stderr,"Moved sparks: %d  Withered sparks: %d (%.2f %%)\n",
323               globalGranStats.tot_sparks, globalGranStats.withered_sparks,
324              ( globalGranStats.tot_sparks == 0 ? 0 :
325                   (float)(100*globalGranStats.withered_sparks)/(float)(globalGranStats.tot_sparks)) );
326      /* Print statistics about priority sparking */
327      if (RtsFlags.GranFlags.DoPrioritySparking) {
328         fprintf(stderr,"About Priority Sparking:\n");
329         fprintf(stderr,"  Total no. NewThreads: %d   Avg. spark queue len: %.2f \n", globalGranStats.tot_sq_probes, (float)globalGranStats.tot_sq_len/(float)globalGranStats.tot_sq_probes);
330      }
331      /* Print statistics about priority sparking */
332      if (RtsFlags.GranFlags.DoPriorityScheduling) {
333         fprintf(stderr,"About Priority Scheduling:\n");
334         fprintf(stderr,"  Total no. of StartThreads: %d (non-end: %d) Avg. thread queue len: %.2f\n", 
335                 globalGranStats.tot_add_threads, globalGranStats.non_end_add_threads, 
336                 (float)globalGranStats.tot_tq_len/(float)globalGranStats.tot_add_threads);
337      }
338      /* Blocking queue statistics */
339      if (1) {
340         fprintf(stderr,"Blocking queue statistcs:\n");
341         fprintf(stderr,"  Total no. of FMBQs generated: %d\n",
342                 globalGranStats.tot_FMBQs);
343         fprintf(stderr,"  Total no. of bqs awakened: %d\n",
344                 globalGranStats.tot_awbq);
345         fprintf(stderr,"  Total length of all bqs: %d\tAvg length of bqs: %.2f\n",
346                 globalGranStats.tot_bq_len, (float)globalGranStats.tot_bq_len/(float)globalGranStats.tot_awbq);
347         fprintf(stderr,"  Percentage of local TSOs in BQs: %.2f\n",
348                 (float)globalGranStats.tot_bq_len*100.0/(float)globalGranStats.tot_bq_len);
349         fprintf(stderr,"  Total time spent processing BQs: %lx\n",
350                 globalGranStats.tot_bq_processing_time);
351      }
352
353      /* Fetch misses and thunk stealing */
354      fprintf(stderr,"Number of fetch misses: %d\n", 
355              globalGranStats.fetch_misses);
356
357      /* Print packet statistics if GUMM fetching is turned on */
358      if (RtsFlags.GranFlags.DoBulkFetching) {
359         fprintf(stderr,"Packet statistcs:\n");
360         fprintf(stderr,"  Total no. of packets: %d   Avg. packet size: %.2f \n", globalGranStats.tot_packets, (float)globalGranStats.tot_packet_size/(float)globalGranStats.tot_packets);
361         fprintf(stderr,"  Total no. of thunks: %d   Avg. thunks/packet: %.2f \n", globalGranStats.tot_thunks, (float)globalGranStats.tot_thunks/(float)globalGranStats.tot_packets);
362         fprintf(stderr,"  Total no. of cuts: %d   Avg. cuts/packet: %.2f\n", globalGranStats.tot_cuts, (float)globalGranStats.tot_cuts/(float)globalGranStats.tot_packets);
363         /* 
364         if (closure_queue_overflows>0) 
365           fprintf(stderr,"  Number of closure queue overflows: %u\n",
366                   closure_queue_overflows);
367         */
368      }
369    } /* RtsFlags.GranFlags.GranSimStats.Global */
370
371 #  if defined(GRAN_COUNT)
372 #  error "GRAN_COUNT not supported; should be parallel ticky profiling, really"
373     fprintf(stderr,"Update count statistics:\n");
374     fprintf(stderr,"  Total number of updates: %u\n",nUPDs);
375     fprintf(stderr,"  Needed to awaken BQ: %u with avg BQ len of: %f\n",
376             nUPDs_BQ,(float)BQ_lens/(float)nUPDs_BQ);
377     fprintf(stderr,"  Number of PAPs: %u\n",nPAPs);
378 #  endif
379
380     fprintf(stderr, "Simulation finished after @ %s @ cycles. %d sparks created, %d sparks ignored. Check %s for details.\n",
381             time_string, sparksCreated, sparksIgnored, gr_filename);
382
383     if (RtsFlags.GranFlags.GranSimStats.Full) 
384       fclose(gr_file);
385 }
386
387 #elif defined(PAR)
388
389 /*
390   Under GUM we print only one line. 
391 */
392 void
393 end_gr_simulation(void)
394 {
395   char time_string[TIME_STR_LEN];
396
397   ullong_format_string(CURRENT_TIME-startTime, time_string, rtsFalse/*no commas!*/);
398
399   fprintf(stderr, "Computation finished after @ %s @ ms. %d sparks created, %d sparks ignored. Check %s for details.\n",
400             time_string, sparksCreated, sparksIgnored, gr_filename);
401
402   if (RtsFlags.ParFlags.ParStats.Full) 
403     fclose(gr_file);
404 }
405 #endif /* PAR */
406
407 //@node Dumping routines,  , Writing to the log-file
408 //@subsection Dumping routines
409
410 //@cindex DumpGranEvent
411 void
412 DumpGranEvent(name, tso)
413 GranEventType name;
414 StgTSO *tso;
415 {
416     DumpRawGranEvent(CURRENT_PROC, (PEs)0, name, tso, END_TSO_QUEUE, (StgInt)0, (StgInt)0);
417 }
418
419 //@cindex DumpRawGranEvent
420 void
421 DumpRawGranEvent(proc, p, name, tso, node, sparkname, len)
422 PEs proc, p;         /* proc ... where it happens; p ... where node lives */
423 GranEventType name;
424 StgTSO *tso;
425 StgClosure *node;
426 StgInt sparkname, len;
427 {
428   FILE *output_file; // DEBUGGING ONLY !!!!!!!!!!!!!!!!!!!!!!!!!1
429   StgWord id;
430   char time_string[TIME_STR_LEN], node_str[NODE_STR_LEN];
431   ullong_format_string(TIME_ON_PROC(proc), time_string, rtsFalse/*no commas!*/);
432
433   output_file = gr_file;
434   ASSERT(output_file!=NULL);
435 # if defined(GRAN)
436   IF_DEBUG(gran,
437            fprintf(stderr, "GRAN: Dumping info to file with handle %#x\n", output_file))
438                    
439   if (RtsFlags.GranFlags.GranSimStats.Suppressed)
440     return;
441 # endif
442
443   id = tso == NULL ? -1 : tso->id;
444   if (node==stgCast(StgClosure*,&END_TSO_QUEUE_closure))
445       strcpy(node_str,"________");  /* "END_TSO_QUEUE"); */
446   else
447       sprintf(node_str,"0x%-6lx",node);
448
449   if (name > GR_EVENT_MAX)
450         name = GR_EVENT_MAX;
451
452   if (BINARY_STATS)
453     barf("binary log files not yet supported");
454 #if 0
455     /* ToDo: fix code for writing binary GrAnSim statistics */
456     switch (name) { 
457       case GR_START:
458       case GR_STARTQ:
459                       grputw(name);
460                       grputw(proc);
461                       abort();        /* die please: a single word */
462                                       /* doesn't represent long long times */
463                       grputw(TIME_ON_PROC(proc));
464                       grputw((StgWord)node);
465                       break;
466       case GR_FETCH:
467       case GR_REPLY:
468       case GR_BLOCK:
469                       grputw(name);
470                       grputw(proc);
471                       abort();        /* die please: a single word */
472                                       /* doesn't represent long long times */
473                       grputw(TIME_ON_PROC(proc));  /* this line is bound to */
474                       grputw(id);                  /*   do the wrong thing */
475                       break;
476       default: 
477                       grputw(name);
478                       grputw(proc);
479                       abort();        /* die please: a single word */
480                                       /* doesn't represent long long times */
481                       grputw(TIME_ON_PROC(proc));
482                       grputw((StgWord)node);
483     }
484 #endif
485   else /* !BINARY_STATS */
486     switch (name) { 
487      case GR_START:
488      case GR_STARTQ:
489         fprintf(output_file,"PE %2u [%s]: %-9s\t%lx\t%s\t[SN %u]\t[sparks %u]\n", 
490                 proc,time_string,gran_event_names[name],
491                 id,node_str,sparkname,len);
492         break;
493      case GR_FETCH:
494      case GR_REPLY:
495      case GR_BLOCK:
496      case GR_STOLEN:
497      case GR_STOLENQ:
498         fprintf(output_file, "PE %2u [%s]: %-9s\t%lx \t%s\t(from %2u)\n",
499                 proc, time_string, gran_event_names[name], 
500                 id,node_str,p);
501         break;
502      case GR_RESUME:
503      case GR_RESUMEQ:
504      case GR_SCHEDULE:
505      case GR_DESCHEDULE:
506         fprintf(output_file,"PE %2u [%s]: %-9s\t%lx \n",
507                 proc,time_string,gran_event_names[name],id);
508         break;
509      case GR_STEALING:
510         fprintf(output_file,"PE %2u [%s]: %-9s\t%lx\t        \t(by %2u)\n",
511                 proc,time_string,gran_event_names[name],id,p);
512         break;
513      case GR_ALLOC:
514         fprintf(output_file,"PE %2u [%s]: %-9s\t%lx\t        \tallocating %u words\n",
515                 proc,time_string,gran_event_names[name],id,len);
516         break;
517      default:
518         fprintf(output_file,"PE %2u [%s]: %-9s\t%lx\t%s\t[sparks %u]\n",
519                 proc,time_string,gran_event_names[name],id,node_str,len);
520     }
521 }
522
523 //@cindex DumpGranInfo
524 void
525 DumpEndEvent(proc, tso, mandatory_thread)
526 PEs proc;
527 StgTSO *tso;
528 rtsBool mandatory_thread;
529 {
530   FILE *output_file; // DEBUGGING ONLY !!!!!!!!!!!!!!!!!!!!!!!!!1
531     char time_string[TIME_STR_LEN];
532     ullong_format_string(CURRENT_TIME, time_string, rtsFalse/*no commas!*/);
533
534   output_file = gr_file;
535   ASSERT(output_file!=NULL);
536 #if defined(GRAN)
537     if (RtsFlags.GranFlags.GranSimStats.Suppressed)
538       return;
539 #endif
540
541     if (BINARY_STATS) {
542     barf("binary log files not yet supported");
543 #if 0
544         grputw(GR_END);
545         grputw(proc);
546         abort(); /* die please: a single word doesn't represent long long times */
547         grputw(CURRENT_TIME); /* this line is bound to fail */
548         grputw(tso->id);
549 #ifdef PAR
550         grputw(0);
551         grputw(0);
552         grputw(0);
553         grputw(0);
554         grputw(0);
555         grputw(0);
556         grputw(0);
557         grputw(0);
558         grputw(0);
559         grputw(0);
560         grputw(0);
561         grputw(0);
562 #else
563         grputw(tso->gran.sparkname);
564         grputw(tso->gran.startedat);
565         grputw(tso->gran.exported);
566         grputw(tso->gran.basicblocks);
567         grputw(tso->gran.allocs);
568         grputw(tso->gran.exectime);
569         grputw(tso->gran.blocktime);
570         grputw(tso->gran.blockcount);
571         grputw(tso->gran.fetchtime);
572         grputw(tso->gran.fetchcount);
573         grputw(tso->gran.localsparks);
574         grputw(tso->gran.globalsparks);
575 #endif
576         grputw(mandatory_thread);
577 #endif /* 0 */
578     } else {
579
580         /*
581          * NB: DumpGranEvent cannot be used because PE may be wrong 
582          * (as well as the extra info)
583          */
584         fprintf(output_file, "PE %2u [%s]: END %lx, SN %u, ST %lu, EXP %c, BB %u, HA %u, RT %u, BT %u (%u), FT %u (%u), LS %u, GS %u, MY %c\n"
585           ,proc
586           ,time_string
587           ,tso->id
588 #if defined(GRAN)               
589           ,tso->gran.sparkname
590           ,tso->gran.startedat
591           ,tso->gran.exported ? 'T' : 'F'
592           ,tso->gran.basicblocks
593           ,tso->gran.allocs
594           ,tso->gran.exectime
595           ,tso->gran.blocktime
596           ,tso->gran.blockcount
597           ,tso->gran.fetchtime
598           ,tso->gran.fetchcount
599           ,tso->gran.localsparks
600           ,tso->gran.globalsparks
601 #elif defined(PAR)
602           ,tso->par.sparkname
603           ,tso->par.startedat
604           ,tso->par.exported ? 'T' : 'F'
605           ,tso->par.basicblocks
606           ,tso->par.allocs
607           ,tso->par.exectime
608           ,tso->par.blocktime
609           ,tso->par.blockcount
610           ,tso->par.fetchtime
611           ,tso->par.fetchcount
612           ,tso->par.localsparks
613           ,tso->par.globalsparks
614 #endif
615           ,mandatory_thread ? 'T' : 'F'
616           );
617     }
618 }
619
620 //@cindex DumpTSO
621 void
622 DumpTSO(tso)
623 StgTSO *tso;
624 {
625   FILE *output_file; // DEBUGGING ONLY !!!!!!!!!!!!!!!!!!!!!!!!!1
626
627   output_file = gr_file;
628   ASSERT(output_file!=NULL);
629   fprintf(stderr,"TSO 0x%lx, NAME 0x%lx, ID %u, LINK 0x%lx, TYPE %s\n"
630           ,tso
631 #if defined(GRAN)
632           ,tso->gran.sparkname
633 #elif defined(PAR)
634           ,tso->par.sparkname
635 #endif
636           ,tso->id
637           ,tso->link
638           ,/*tso->state==T_MAIN?"MAIN":
639            TSO_TYPE(tso)==T_FAIL?"FAIL":
640            TSO_TYPE(tso)==T_REQUIRED?"REQUIRED":
641            TSO_TYPE(tso)==T_ADVISORY?"ADVISORY":
642            */
643            "???"
644           );
645           
646   fprintf(output_file,"TSO %lx: SN %u, ST %u, GBL %c, BB %u, HA %u, RT %u, BT %u (%u), FT %u (%u) LS %u, GS %u\n"
647           ,tso->id
648 #if defined(GRAN)
649           ,tso->gran.sparkname
650           ,tso->gran.startedat
651           ,tso->gran.exported?'T':'F'
652           ,tso->gran.basicblocks
653           ,tso->gran.allocs
654           ,tso->gran.exectime
655           ,tso->gran.blocktime
656           ,tso->gran.blockcount
657           ,tso->gran.fetchtime
658           ,tso->gran.fetchcount
659           ,tso->gran.localsparks
660           ,tso->gran.globalsparks
661 #elif defined(PAR)
662           ,tso->par.sparkname
663           ,tso->par.startedat
664           ,tso->par.exported?'T':'F'
665           ,tso->par.basicblocks
666           ,tso->par.allocs
667           ,tso->par.exectime
668           ,tso->par.blocktime
669           ,tso->par.blockcount
670           ,tso->par.fetchtime
671           ,tso->par.fetchcount
672           ,tso->par.localsparks
673           ,tso->par.globalsparks
674 #endif
675           );
676 }
677
678 #if 0
679 /*
680   ToDo: fix binary output of log files, and support new log file format.
681 */
682 /*
683    Output a terminate event and an 8-byte time.
684 */
685
686 //@cindex grterminate
687 void
688 grterminate(v)
689 rtsTime v;
690 {
691   if (!BINARY_STATS) 
692     barf("grterminate: binary statistics not enabled\n");
693
694 # if defined(GRAN)
695     if (RtsFlags.GranFlags.GranSimStats.Suppressed)
696       return;
697 # endif
698
699     DumpGranEvent(GR_TERMINATE, stgCast(StgTSO*,&END_TSO_QUEUE_closure));
700
701     if (sizeof(rtsTime) == 4) {
702       putc('\0', gr_file);
703       putc('\0', gr_file);
704       putc('\0', gr_file);
705       putc('\0', gr_file);
706     } else {
707       putc(v >> 56l, gr_file);
708       putc((v >> 48l) & 0xffl, gr_file);
709       putc((v >> 40l) & 0xffl, gr_file);
710       putc((v >> 32l) & 0xffl, gr_file);
711     }
712     putc((v >> 24l) & 0xffl, gr_file);
713     putc((v >> 16l) & 0xffl, gr_file);
714     putc((v >> 8l) & 0xffl, gr_file);
715     putc(v & 0xffl, gr_file);
716 }
717
718 /*
719    Length-coded output: first 3 bits contain length coding
720
721      00x        1 byte
722      01x        2 bytes
723      10x        4 bytes
724      110        8 bytes
725      111        5 or 9 bytes
726 */
727
728 //@cindex grputw
729 void
730 grputw(v)
731 rtsTime v;
732 {
733   if (!BINARY_STATS) 
734     barf("grputw: binary statistics not enabled\n");
735
736 # if defined(GRAN)
737     if (RtsFlags.GranFlags.GranSimStats.Suppressed)
738       return;
739 # endif
740
741     if (v <= 0x3fl) {                           /* length v = 1 byte */ 
742         fputc(v & 0x3f, gr_file);
743     } else if (v <= 0x3fffl) {                  /* length v = 2 byte */ 
744         fputc((v >> 8l) | 0x40l, gr_file);
745         fputc(v & 0xffl, gr_file);
746     } else if (v <= 0x3fffffffl) {              /* length v = 4 byte */ 
747         fputc((v >> 24l) | 0x80l, gr_file);
748         fputc((v >> 16l) & 0xffl, gr_file);
749         fputc((v >> 8l) & 0xffl, gr_file);
750         fputc(v & 0xffl, gr_file);
751     } else if (sizeof(TIME) == 4) {
752         fputc(0x70, gr_file);
753         fputc((v >> 24l) & 0xffl, gr_file);
754         fputc((v >> 16l) & 0xffl, gr_file);
755         fputc((v >> 8l) & 0xffl, gr_file);
756         fputc(v & 0xffl, gr_file);
757     } else {
758         if (v <= 0x3fffffffffffffl)
759             putc((v >> 56l) | 0x60l, gr_file);
760         else {
761             putc(0x70, gr_file);
762             putc((v >> 56l) & 0xffl, gr_file);
763         }
764
765         putc((v >> 48l) & 0xffl, gr_file);
766         putc((v >> 40l) & 0xffl, gr_file);
767         putc((v >> 32l) & 0xffl, gr_file);
768         putc((v >> 24l) & 0xffl, gr_file);
769         putc((v >> 16l) & 0xffl, gr_file);
770         putc((v >> 8l) & 0xffl, gr_file);
771         putc(v & 0xffl, gr_file);
772     }
773 }
774 #endif /* 0 */
775
776 #endif /* GRAN || PAR   whole file */