2 Time-stamp: <Sat Dec 04 1999 19:43:39 Stardate: [-30]3999.10 hwloidl>
4 Basic functions for use in either GranSim or GUM.
7 #if defined(GRAN) || defined(PAR) /* whole file */
11 //* Variables and constants::
12 //* Writing to the log-file::
13 //* Dumping routines::
16 //@node Includes, Variables and constants
17 //@subsection Includes
22 #include "GranSimRts.h"
23 #include "ParallelRts.h"
26 //@node Variables and constants, Writing to the log-file, Includes
27 //@subsection Variables and constants
29 /* Where to write the log file */
31 char gr_filename[STATS_FILENAME_MAXLEN];
33 //@node Writing to the log-file, Dumping routines, Variables and constants
34 //@subsection Writing to the log-file
36 Writing to the log-file
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.
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
48 //@cindex init_gr_simulation
51 init_gr_simulation(rts_argc, rts_argv, prog_argc, prog_argv)
52 char *prog_argv[], *rts_argv[];
53 int prog_argc, rts_argc;
56 char *extension = RtsFlags.GranFlags.GranSimStats.Binary ? "gb" : "gr";
58 if (RtsFlags.GranFlags.GranSimStats.Global)
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;
68 if (RtsFlags.GranFlags.GranSimStats.Suppressed)
71 if (!RtsFlags.GranFlags.GranSimStats.Full)
74 sprintf(gr_filename, GR_FILENAME_FMT, prog_argv[0], extension);
76 if ((gr_file = fopen(gr_filename, "w")) == NULL) {
77 barf("Can't open granularity simulation report file %s\n",
81 setbuf(gr_file, NULL); // for debugging turn buffering off
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);
91 fputs("+RTS ", gr_file);
93 for (i = 0; i < rts_argc; ++i) {
94 fputs(rts_argv[i], gr_file);
99 fputs("\nStart time: ", gr_file);
100 fputs(time_str(), gr_file); /* defined in RtsUtils.c */
101 fputc('\n', gr_file);
103 fputs("\n\n--------------------\n\n", gr_file);
105 fputs("General Parameters:\n\n", gr_file);
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" :
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" :
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);
128 fprintf(gr_file, "Bulk Fetching: Fetch as many closures as possible (Packet Size = %d closures)\n",
129 RtsFlags.GranFlags.packBufferSize);
131 fprintf(gr_file, "Incremental Fetching: Fetch Exactly One Closure in Each Packet\n");
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":
147 if (RtsFlags.GranFlags.DoPrioritySparking)
148 fprintf(gr_file, "Priority Sparking (i.e. keep sparks ordered by priority)\n");
150 if (RtsFlags.GranFlags.DoPriorityScheduling)
151 fprintf(gr_file, "Priority Scheduling (i.e. keep threads ordered by priority)\n");
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);
163 fputs("Communication Metrics:\n\n", 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);
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);
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);
189 /* binary log files are currently not supported */
190 if (RtsFlags.GranFlags.GranSimStats.Binary)
191 grputw(sizeof(rtsTime));
200 init_gr_simulation(rts_argc, rts_argv, prog_argc, prog_argv)
201 char *prog_argv[], *rts_argv[];
202 int prog_argc, rts_argc;
205 char time_string[TIME_STR_LEN], node_str[NODE_STR_LEN];
206 char *extension = RtsFlags.ParFlags.ParStats.Binary ? "gb" : "gr";
208 sprintf(gr_filename, GR_FILENAME_FMT_GUM, prog_argv[0], thisPE, extension);
210 if (!RtsFlags.ParFlags.ParStats.Full)
213 if ((gr_file = fopen(gr_filename, "w")) == NULL)
214 barf("Can't open activity report file %s\n", gr_filename);
216 setbuf(gr_file, NULL); // for debugging turn buffering off
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);
225 fputs("+RTS ", gr_file);
227 for (i = 0; i < rts_argc; ++i) {
228 fputs(rts_argv[i], gr_file);
232 fputc('\n', gr_file);
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);
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);
244 IF_PAR_DEBUG(verbose,
245 belch("== Start-time: %ld (%s)",
246 startTime, time_string));
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)));
256 fprintf(gr_file, "PE %2u [%lu]: TIME\n", thisPE, (TIME) startTime);
258 /* binary log files are currently not supported */
259 if (RtsFlags.GranFlags.GranSimStats.Binary)
260 grputw(sizeof(rtsTime));
267 //@cindex end_gr_simulation
270 end_gr_simulation(void)
272 char time_string[TIME_STR_LEN];
274 ullong_format_string(CURRENT_TIME, time_string, rtsFalse/*no commas!*/);
276 if (RtsFlags.GranFlags.GranSimStats.Suppressed)
279 /* Print event stats */
280 if (RtsFlags.GranFlags.GranSimStats.Global) {
283 fprintf(stderr,"Total yields: %d\n",
284 globalGranStats.tot_yields);
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");
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);
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");
304 if (RtsFlags.GranFlags.proc+1 % 4 != 0) fprintf(stderr,"\n");
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])) ));
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);
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);
338 /* Blocking queue statistics */
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);
353 /* Fetch misses and thunk stealing */
354 fprintf(stderr,"Number of fetch misses: %d\n",
355 globalGranStats.fetch_misses);
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);
364 if (closure_queue_overflows>0)
365 fprintf(stderr," Number of closure queue overflows: %u\n",
366 closure_queue_overflows);
369 } /* RtsFlags.GranFlags.GranSimStats.Global */
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);
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);
383 if (RtsFlags.GranFlags.GranSimStats.Full)
390 Under GUM we print only one line.
393 end_gr_simulation(void)
395 char time_string[TIME_STR_LEN];
397 ullong_format_string(CURRENT_TIME-startTime, time_string, rtsFalse/*no commas!*/);
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);
402 if (RtsFlags.ParFlags.ParStats.Full)
407 //@node Dumping routines, , Writing to the log-file
408 //@subsection Dumping routines
410 //@cindex DumpGranEvent
412 DumpGranEvent(name, tso)
416 DumpRawGranEvent(CURRENT_PROC, (PEs)0, name, tso, END_TSO_QUEUE, (StgInt)0, (StgInt)0);
419 //@cindex DumpRawGranEvent
421 DumpRawGranEvent(proc, p, name, tso, node, sparkname, len)
422 PEs proc, p; /* proc ... where it happens; p ... where node lives */
426 StgInt sparkname, len;
428 FILE *output_file; // DEBUGGING ONLY !!!!!!!!!!!!!!!!!!!!!!!!!1
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!*/);
433 output_file = gr_file;
434 ASSERT(output_file!=NULL);
437 fprintf(stderr, "GRAN: Dumping info to file with handle %#x\n", output_file))
439 if (RtsFlags.GranFlags.GranSimStats.Suppressed)
443 id = tso == NULL ? -1 : tso->id;
444 if (node==stgCast(StgClosure*,&END_TSO_QUEUE_closure))
445 strcpy(node_str,"________"); /* "END_TSO_QUEUE"); */
447 sprintf(node_str,"0x%-6lx",node);
449 if (name > GR_EVENT_MAX)
453 barf("binary log files not yet supported");
455 /* ToDo: fix code for writing binary GrAnSim statistics */
461 abort(); /* die please: a single word */
462 /* doesn't represent long long times */
463 grputw(TIME_ON_PROC(proc));
464 grputw((StgWord)node);
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 */
479 abort(); /* die please: a single word */
480 /* doesn't represent long long times */
481 grputw(TIME_ON_PROC(proc));
482 grputw((StgWord)node);
485 else /* !BINARY_STATS */
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);
498 fprintf(output_file, "PE %2u [%s]: %-9s\t%lx \t%s\t(from %2u)\n",
499 proc, time_string, gran_event_names[name],
506 fprintf(output_file,"PE %2u [%s]: %-9s\t%lx \n",
507 proc,time_string,gran_event_names[name],id);
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);
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);
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);
523 //@cindex DumpGranInfo
525 DumpEndEvent(proc, tso, mandatory_thread)
528 rtsBool mandatory_thread;
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!*/);
534 output_file = gr_file;
535 ASSERT(output_file!=NULL);
537 if (RtsFlags.GranFlags.GranSimStats.Suppressed)
542 barf("binary log files not yet supported");
546 abort(); /* die please: a single word doesn't represent long long times */
547 grputw(CURRENT_TIME); /* this line is bound to fail */
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);
576 grputw(mandatory_thread);
581 * NB: DumpGranEvent cannot be used because PE may be wrong
582 * (as well as the extra info)
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"
591 ,tso->gran.exported ? 'T' : 'F'
592 ,tso->gran.basicblocks
596 ,tso->gran.blockcount
598 ,tso->gran.fetchcount
599 ,tso->gran.localsparks
600 ,tso->gran.globalsparks
604 ,tso->par.exported ? 'T' : 'F'
605 ,tso->par.basicblocks
612 ,tso->par.localsparks
613 ,tso->par.globalsparks
615 ,mandatory_thread ? 'T' : 'F'
625 FILE *output_file; // DEBUGGING ONLY !!!!!!!!!!!!!!!!!!!!!!!!!1
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"
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":
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"
651 ,tso->gran.exported?'T':'F'
652 ,tso->gran.basicblocks
656 ,tso->gran.blockcount
658 ,tso->gran.fetchcount
659 ,tso->gran.localsparks
660 ,tso->gran.globalsparks
664 ,tso->par.exported?'T':'F'
665 ,tso->par.basicblocks
672 ,tso->par.localsparks
673 ,tso->par.globalsparks
680 ToDo: fix binary output of log files, and support new log file format.
683 Output a terminate event and an 8-byte time.
686 //@cindex grterminate
692 barf("grterminate: binary statistics not enabled\n");
695 if (RtsFlags.GranFlags.GranSimStats.Suppressed)
699 DumpGranEvent(GR_TERMINATE, stgCast(StgTSO*,&END_TSO_QUEUE_closure));
701 if (sizeof(rtsTime) == 4) {
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);
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);
719 Length-coded output: first 3 bits contain length coding
734 barf("grputw: binary statistics not enabled\n");
737 if (RtsFlags.GranFlags.GranSimStats.Suppressed)
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);
758 if (v <= 0x3fffffffffffffl)
759 putc((v >> 56l) | 0x60l, gr_file);
762 putc((v >> 56l) & 0xffl, gr_file);
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);
776 #endif /* GRAN || PAR whole file */