1
2 /*
3 ** sysspec.c
4 ** System-specific routines.
5 **
6 ** BYTEmark (tm)
7 ** BYTE's Native Mode Benchmarks
8 ** Rick Grehan, BYTE Magazine
9 **
10 ** Creation:
11 ** Revision: 3/95;10/95
12 **
13 ** DISCLAIMER
14 ** The source, executable, and documentation files that comprise
15 ** the BYTEmark benchmarks are made available on an "as is" basis.
16 ** This means that we at BYTE Magazine have made every reasonable
17 ** effort to verify that the there are no errors in the source and
18 ** executable code. We cannot, however, guarantee that the programs
19 ** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
20 ** no claims in regard to the fitness of the source code, executable
21 ** code, and documentation of the BYTEmark.
22 ** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
23 ** of McGraw-Hill cannot be held responsible for any damages resulting
24 ** from the use of this code or the results obtained from using
25 ** this code.
26 */
27
28 /***********************************
29 ** SYSTEM-SPECIFIC ROUTINES **
30 ************************************
31 **
32 ** These are the routines that provide functions that are
33 ** system-specific. If the benchmarks are to be ported
34 ** to new hardware/new O.S., this is the first place to
35 ** start.
36 */
37 #include "sysspec.h"
38
39 #ifdef DOS16
40 #include <io.h>
41 #include <fcntl.h>
42 #include <sys\stat.h>
43 #endif
44 /*********************************
45 ** MEMORY MANAGEMENT ROUTINES **
46 *********************************/
47
48
49 /****************************
50 ** AllocateMemory
51 ** This routine returns a void pointer to a memory
52 ** block. The size of the memory block is given in bytes
53 ** as the first argument. This routine also returns an
54 ** error code in the second argument.
55 ** 10/95 Update:
56 ** Added an associative array for memory alignment reasons.
57 ** mem_array[2][MEM_ARRAY_SIZE]
58 ** mem_array[0][n] = Actual address (from malloc)
59 ** mem_array[1][n] = Aligned address
60 ** Currently, mem_array[][] is only used if you use malloc;
61 ** it is not used for the 16-bit DOS and MAC versions.
62 */
AllocateMemory(unsigned long nbytes,int * errorcode)63 farvoid *AllocateMemory(unsigned long nbytes, /* # of bytes to alloc */
64 int *errorcode) /* Returned error code */
65 {
66 #ifdef DOS16MEM
67 union REGS registers;
68 unsigned short nparas; /* # of paragraphs */
69
70 /*
71 ** Set # of paragraphs to nbytes/16 +1. The +1 is a
72 ** slop factor.
73 */
74 nparas=(unsigned short)(nbytes/16L) + 1;
75
76 /*
77 ** Set incoming registers.
78 */
79 registers.h.ah=0x48; /* Allocate memory */
80 registers.x.bx=nparas; /* # of paragraphs */
81
82
83 intdos(®isters,®isters); /* Call DOS */
84
85 /*
86 ** See if things succeeded.
87 */
88 if(registers.x.cflag)
89 { printf("error: %d Lgst: %d\n",registers.x.ax,registers.x.bx);
90 *errorcode=ERROR_MEMORY;
91 return((farvoid *)NULL);
92 }
93
94 /*
95 ** Create a farvoid pointer to return.
96 */
97 *errorcode=0;
98 return((farvoid *)MK_FP(registers.x.ax,0));
99
100 #endif
101
102 #ifdef MACMEM
103 /*
104 ** For MAC CodeWarrior, we'll use the MacOS NewPtr call
105 */
106 farvoid *returnval;
107 returnval=(farvoid *)NewPtr((Size)nbytes);
108 if(returnval==(farvoid *)NULL)
109 *errorcode=ERROR_MEMORY;
110 else
111 *errorcode=0;
112 return(returnval);
113 #endif
114
115 #ifdef MALLOCMEM
116 /*
117 ** Everyone else, its pretty straightforward, given
118 ** that you use a 32-bit compiler which treats size_t as
119 ** a 4-byte entity.
120 */
121 farvoid *returnval; /* Return value */
122 ulong true_addr; /* True address */
123 ulong adj_addr; /* Adjusted address */
124
125 returnval=(farvoid *)malloc((size_t)(nbytes+2L*(long)global_align));
126 if(returnval==(farvoid *)NULL)
127 *errorcode=ERROR_MEMORY;
128 else
129 *errorcode=0;
130
131 /*
132 ** Check for alignment
133 */
134 adj_addr=true_addr=(ulong)returnval;
135 if(global_align==0)
136 {
137 if(AddMemArray(true_addr, adj_addr))
138 *errorcode=ERROR_MEMARRAY_FULL;
139 return(returnval);
140 }
141
142 if(global_align==1)
143 {
144 if(true_addr%2==0) adj_addr++;
145 }
146 else
147 {
148 while(adj_addr%global_align!=0) ++adj_addr;
149 if(adj_addr%(global_align*2)==0) adj_addr+=global_align;
150 }
151 returnval=(void *)adj_addr;
152 if(AddMemArray(true_addr,adj_addr))
153 *errorcode=ERROR_MEMARRAY_FULL;
154 return(returnval);
155 #endif
156
157 }
158
159
160 /****************************
161 ** FreeMemory
162 ** This is the reverse of AllocateMemory. The memory
163 ** block passed in is freed. Should an error occur,
164 ** that error is returned in errorcode.
165 */
FreeMemory(farvoid * mempointer,int * errorcode)166 void FreeMemory(farvoid *mempointer, /* Pointer to memory block */
167 int *errorcode)
168 {
169 #ifdef DOS16MEM
170 /*
171 ** 16-bit DOS VERSION!!
172 */
173 unsigned int segment;
174 unsigned int offset;
175 union REGS registers;
176 struct SREGS sregisters;
177
178 /*
179 ** First get the segment/offset of the farvoid pointer.
180 */
181 segment=FP_SEG(mempointer);
182 offset=FP_OFF(mempointer);
183
184 /*
185 ** Align the segment properly. For as long as offset > 16,
186 ** subtract 16 from offset and add 1 to segment.
187 */
188 while(offset>=16)
189 { offset-=16;
190 segment++;
191 }
192
193 /*
194 ** Build the call to DOS
195 */
196 registers.h.ah=0x49; /* Free memory */
197 sregisters.es=segment;
198
199 intdosx(®isters,®isters,&sregisters);
200
201 /*
202 ** Check for error
203 */
204 if(registers.x.cflag)
205 { *errorcode=ERROR_MEMORY;
206 return;
207 }
208
209 *errorcode=0;
210 return;
211 #endif
212
213 #ifdef MACMEM
214 DisposPtr((Ptr)mempointer);
215 *errorcode=0;
216 return;
217 #endif
218
219 #ifdef MALLOCMEM
220 ulong adj_addr, true_addr;
221
222 /* Locate item in memory array */
223 adj_addr=(ulong)mempointer;
224 if(RemoveMemArray(adj_addr, &true_addr))
225 { *errorcode=ERROR_MEMARRAY_NFOUND;
226 return;
227 }
228 mempointer=(void *)true_addr;
229 free(mempointer);
230 *errorcode=0;
231 return;
232 #endif
233 }
234
235 /****************************
236 ** MoveMemory
237 ** Moves n bytes from a to b. Handles overlap.
238 ** In most cases, this is just a memmove operation.
239 ** But, not in DOS....noooo....
240 */
MoveMemory(farvoid * destination,farvoid * source,unsigned long nbytes)241 void MoveMemory( farvoid *destination, /* Destination address */
242 farvoid *source, /* Source address */
243 unsigned long nbytes)
244 {
245
246 /* +++16-bit DOS VERSION+++ */
247 #ifdef DOS16MEM
248
249 FarDOSmemmove( destination, source, nbytes);
250
251 #else
252
253 memmove(destination, source, nbytes);
254
255 #endif
256 }
257
258 #ifdef DOS16MEM
259
260 /****************************
261 ** FarDOSmemmove
262 ** Performs the same function as memmove for DOS when
263 ** the arrays are defined with far pointers.
264 */
FarDOSmemmove(farvoid * destination,farvoid * source,unsigned long nbytes)265 void FarDOSmemmove(farvoid *destination, /* Destination pointer */
266 farvoid *source, /* Source pointer */
267 unsigned long nbytes) /* # of bytes to move */
268 {
269 unsigned char huge *uchsource; /* Temp source */
270 unsigned char huge *uchdest; /* Temp destination */
271 unsigned long saddr; /* Source "true" address */
272 unsigned long daddr; /* Destination "true" address */
273
274
275 /*
276 ** Get unsigned char pointer equivalents
277 */
278 uchsource=(unsigned char huge *)source;
279 uchdest=(unsigned char huge *)destination;
280
281 /*
282 ** Calculate true address of source and destination and
283 ** compare.
284 */
285 saddr=(unsigned long)(FP_SEG(source)*16 + FP_OFF(source));
286 daddr=(unsigned long)(FP_SEG(destination)*16 + FP_OFF(destination));
287
288 if(saddr > daddr)
289 {
290 /*
291 ** Source is greater than destination.
292 ** Use a series of standard move operations.
293 ** We'll move 65535 bytes at a time.
294 */
295 while(nbytes>=65535L)
296 { _fmemmove((farvoid *)uchdest,
297 (farvoid *)uchsource,
298 (size_t) 65535);
299 uchsource+=65535; /* Advance pointers */
300 uchdest+=65535;
301 nbytes-=65535;
302 }
303
304 /*
305 ** Move remaining bytes
306 */
307 if(nbytes!=0L)
308 _fmemmove((farvoid *)uchdest,
309 (farvoid *)uchsource,
310 (size_t)(nbytes & 0xFFFF));
311
312 }
313 else
314 {
315 /*
316 ** Destination is greater than source.
317 ** Advance pointers to the end of their
318 ** respective blocks.
319 */
320 uchsource+=nbytes;
321 uchdest+=nbytes;
322
323 /*
324 ** Again, move 65535 bytes at a time. However,
325 ** "back" the pointers up before doing the
326 ** move.
327 */
328 while(nbytes>=65535L)
329 {
330 uchsource-=65535;
331 uchdest-=65535;
332 _fmemmove((farvoid *)uchdest,
333 (farvoid *)uchsource,
334 (size_t) 65535);
335 nbytes-=65535;
336 }
337
338 /*
339 ** Move remaining bytes.
340 */
341 if(nbytes!=0L)
342 { uchsource-=nbytes;
343 uchdest-=nbytes;
344 _fmemmove((farvoid *)uchdest,
345 (farvoid *)uchsource,
346 (size_t)(nbytes & 0xFFFF));
347 }
348 }
349 return;
350 }
351 #endif
352
353 /***********************************
354 ** MEMORY ARRAY HANDLING ROUTINES **
355 ***********************************/
356 /****************************
357 ** InitMemArray
358 ** Initialize the memory array. This simply amounts to
359 ** setting mem_array_ents to zero, indicating that there
360 ** isn't anything in the memory array.
361 */
InitMemArray(void)362 void InitMemArray(void)
363 {
364 mem_array_ents=0;
365 return;
366 }
367
368 /***************************
369 ** AddMemArray
370 ** Add a pair of items to the memory array.
371 ** true_addr is the true address (mem_array[0][n])
372 ** adj_addr is the adjusted address (mem_array[0][n])
373 ** Returns 0 if ok
374 ** -1 if not enough room
375 */
AddMemArray(ulong true_addr,ulong adj_addr)376 int AddMemArray(ulong true_addr,
377 ulong adj_addr)
378 {
379 if(mem_array_ents>=MEM_ARRAY_SIZE)
380 return(-1);
381
382 mem_array[0][mem_array_ents]=true_addr;
383 mem_array[1][mem_array_ents]=adj_addr;
384 mem_array_ents++;
385 return(0);
386 }
387
388 /*************************
389 ** RemoveMemArray
390 ** Given an adjusted address value (mem_array[1][n]), locate
391 ** the entry and remove it from the mem_array.
392 ** Also returns the associated true address.
393 ** Returns 0 if ok
394 ** -1 if not found.
395 */
RemoveMemArray(ulong adj_addr,ulong * true_addr)396 int RemoveMemArray(ulong adj_addr,ulong *true_addr)
397 {
398 int i,j;
399
400 /* Locate the item in the array. */
401 for(i=0;i<mem_array_ents;i++)
402 if(mem_array[1][i]==adj_addr)
403 { /* Found it..bubble stuff down */
404 *true_addr=mem_array[0][i];
405 j=i;
406 while(j+1<mem_array_ents)
407 { mem_array[0][j]=mem_array[0][j+1];
408 mem_array[1][j]=mem_array[1][j+1];
409 j++;
410 }
411 mem_array_ents--;
412 return(0); /* Return if found */
413 }
414
415 /* If we made it here...something's wrong...show error */
416 return(-1);
417 }
418
419 /**********************************
420 ** FILE HANDLING ROUTINES **
421 **********************************/
422
423 /****************************
424 ** CreateFile
425 ** This routine accepts a filename for an argument and
426 ** creates that file in the current directory (unless the
427 ** name contains a path that overrides the current directory).
428 ** Note that the routine does not OPEN the file.
429 ** If the file exists, it is truncated to length 0.
430 */
CreateFile(char * filename,int * errorcode)431 void CreateFile(char *filename,
432 int *errorcode)
433 {
434
435 #ifdef DOS16
436 /*
437 ** DOS VERSION!!
438 */
439 int fhandle; /* File handle used internally */
440
441 fhandle=open(filename,O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
442
443 if(fhandle==-1)
444 *errorcode=ERROR_FILECREATE;
445 else
446 *errorcode=0;
447
448 /*
449 ** Since all we're doing here is creating the file,
450 ** go ahead and close it.
451 */
452 close(fhandle);
453
454 return;
455 #endif
456
457 #ifdef LINUX
458 FILE *fhandle; /* File handle used internally */
459
460 fhandle=fopen(filename,"w");
461
462 if(fhandle==NULL)
463 *errorcode=ERROR_FILECREATE;
464 else
465 *errorcode=0;
466
467 /*
468 ** Since all we're doing here is creating the file,
469 ** go ahead and close it.
470 */
471 fclose(fhandle);
472
473 return;
474 #endif
475 }
476
477 /****************************
478 ** bmOpenFile
479 ** Opens the file given by fname, returning its handle.
480 ** If an error occurs, returns its code in errorcode.
481 ** The file is opened in read-write exclusive mode.
482 */
483 #ifdef DOS16
484 /*
485 ** DOS VERSION!!
486 */
487
bmOpenFile(char * fname,int * errorcode)488 int bmOpenFile(char *fname, /* File name */
489 int *errorcode) /* Error code returned */
490 {
491
492 int fhandle; /* Returned file handle */
493
494 fhandle=open(fname,O_BINARY | O_RDWR, S_IREAD | S_IWRITE);
495
496 if(fhandle==-1)
497 *errorcode=ERROR_FILEOPEN;
498 else
499 *errorcode=0;
500
501 return(fhandle);
502 }
503 #endif
504
505
506 #ifdef LINUX
507
bmOpenFile(char * fname,int * errorcode)508 FILE *bmOpenFile(char *fname, /* File name */
509 int *errorcode) /* Error code returned */
510 {
511
512 FILE *fhandle; /* Returned file handle */
513
514 fhandle=fopen(fname,"w+");
515
516 if(fhandle==NULL)
517 *errorcode=ERROR_FILEOPEN;
518 else
519 *errorcode=0;
520
521 return(fhandle);
522 }
523 #endif
524
525
526 /****************************
527 ** CloseFile
528 ** Closes the file identified by fhandle.
529 ** A more inocuous routine there never was.
530 */
531 #ifdef DOS16
532 /*
533 ** DOS VERSION!!!
534 */
CloseFile(int fhandle,int * errorcode)535 void CloseFile(int fhandle, /* File handle */
536 int *errorcode) /* Returned error code */
537 {
538
539 close(fhandle);
540 *errorcode=0;
541 return;
542 }
543 #endif
544 #ifdef LINUX
CloseFile(FILE * fhandle,int * errorcode)545 void CloseFile(FILE *fhandle, /* File handle */
546 int *errorcode) /* Returned error code */
547 {
548 fclose(fhandle);
549 *errorcode=0;
550 return;
551 }
552 #endif
553
554 /****************************
555 ** readfile
556 ** Read bytes from an opened file. This routine
557 ** is a combination seek-and-read.
558 ** Note that this routine expects the offset to be from
559 ** the beginning of the file.
560 */
561 #ifdef DOS16
562 /*
563 ** DOS VERSION!!
564 */
565
readfile(int fhandle,unsigned long offset,unsigned long nbytes,void * buffer,int * errorcode)566 void readfile(int fhandle, /* File handle */
567 unsigned long offset, /* Offset into file */
568 unsigned long nbytes, /* # of bytes to read */
569 void *buffer, /* Buffer to read into */
570 int *errorcode) /* Returned error code */
571 {
572
573 long newoffset; /* New offset by lseek */
574 int readcode; /* Return code from read */
575
576 /*
577 ** Presume success.
578 */
579 *errorcode=0;
580
581 /*
582 ** Seek to the proper offset.
583 */
584 newoffset=lseek(fhandle,(long)offset,SEEK_SET);
585 if(newoffset==-1L)
586 { *errorcode=ERROR_FILESEEK;
587 return;
588 }
589
590 /*
591 ** Do the read.
592 */
593 readcode=read(fhandle,buffer,(unsigned)(nbytes & 0xFFFF));
594 if(readcode==-1)
595 *errorcode=ERROR_FILEREAD;
596
597 return;
598 }
599 #endif
600 #ifdef LINUX
readfile(FILE * fhandle,unsigned long offset,unsigned long nbytes,void * buffer,int * errorcode)601 void readfile(FILE *fhandle, /* File handle */
602 unsigned long offset, /* Offset into file */
603 unsigned long nbytes, /* # of bytes to read */
604 void *buffer, /* Buffer to read into */
605 int *errorcode) /* Returned error code */
606 {
607
608 long newoffset; /* New offset by fseek */
609 size_t nelems; /* Expected return code from read */
610 size_t readcode; /* Actual return code from read */
611
612 /*
613 ** Presume success.
614 */
615 *errorcode=0;
616
617 /*
618 ** Seek to the proper offset.
619 */
620 newoffset=fseek(fhandle,(long)offset,SEEK_SET);
621 if(newoffset==-1L)
622 { *errorcode=ERROR_FILESEEK;
623 return;
624 }
625
626 /*
627 ** Do the read.
628 */
629 nelems=(size_t)(nbytes & 0xFFFF);
630 readcode=fread(buffer,(size_t)1,nelems,fhandle);
631 if(readcode!=nelems)
632 *errorcode=ERROR_FILEREAD;
633
634 return;
635 }
636 #endif
637
638 /****************************
639 ** writefile
640 ** writes bytes to an opened file. This routine is
641 ** a combination seek-and-write.
642 ** Note that this routine expects the offset to be from
643 ** the beinning of the file.
644 */
645 #ifdef DOS16
646 /*
647 ** DOS VERSION!!
648 */
649
writefile(int fhandle,unsigned long offset,unsigned long nbytes,void * buffer,int * errorcode)650 void writefile(int fhandle, /* File handle */
651 unsigned long offset, /* Offset into file */
652 unsigned long nbytes, /* # of bytes to read */
653 void *buffer, /* Buffer to read into */
654 int *errorcode) /* Returned error code */
655 {
656
657 long newoffset; /* New offset by lseek */
658 int writecode; /* Return code from write */
659
660 /*
661 ** Presume success.
662 */
663 *errorcode=0;
664
665 /*
666 ** Seek to the proper offset.
667 */
668 newoffset=lseek(fhandle,(long)offset,SEEK_SET);
669 if(newoffset==-1L)
670 { *errorcode=ERROR_FILESEEK;
671 return;
672 }
673
674 /*
675 ** Do the write.
676 */
677 writecode=write(fhandle,buffer,(unsigned)(nbytes & 0xFFFF));
678 if(writecode==-1)
679 *errorcode=ERROR_FILEWRITE;
680
681 return;
682 }
683 #endif
684
685 #ifdef LINUX
686
writefile(FILE * fhandle,unsigned long offset,unsigned long nbytes,void * buffer,int * errorcode)687 void writefile(FILE *fhandle, /* File handle */
688 unsigned long offset, /* Offset into file */
689 unsigned long nbytes, /* # of bytes to read */
690 void *buffer, /* Buffer to read into */
691 int *errorcode) /* Returned error code */
692 {
693
694 long newoffset; /* New offset by lseek */
695 size_t nelems; /* Expected return code from write */
696 size_t writecode; /* Actual return code from write */
697
698 /*
699 ** Presume success.
700 */
701 *errorcode=0;
702
703 /*
704 ** Seek to the proper offset.
705 */
706 newoffset=fseek(fhandle,(long)offset,SEEK_SET);
707 if(newoffset==-1L)
708 { *errorcode=ERROR_FILESEEK;
709 return;
710 }
711
712 /*
713 ** Do the write.
714 */
715 nelems=(size_t)(nbytes & 0xFFFF);
716 writecode=fwrite(buffer,(size_t)1,nelems,fhandle);
717 if(writecode==nelems)
718 *errorcode=ERROR_FILEWRITE;
719
720 return;
721 }
722 #endif
723
724
725 /********************************
726 ** ERROR HANDLING ROUTINES **
727 ********************************/
728
729 /****************************
730 ** ReportError
731 ** Report error message condition.
732 */
ReportError(char * errorcontext,int errorcode)733 void ReportError(char *errorcontext, /* Error context string */
734 int errorcode) /* Error code number */
735 {
736
737 /*
738 ** Display error context
739 */
740 printf("ERROR CONDITION\nContext: %s\n",errorcontext);
741
742 /*
743 ** Display code
744 */
745 printf("Code: %d",errorcode);
746
747 return;
748 }
749
750 /****************************
751 ** ErrorExit
752 ** Peforms an exit from an error condition.
753 */
ErrorExit()754 void ErrorExit()
755 {
756
757 /*
758 ** For profiling on the Mac with MetroWerks -- 11/17/94 RG
759 ** Have to do this to turn off profiler.
760 */
761 #ifdef MACCWPROF
762 #if __profile__
763 ProfilerTerm();
764 #endif
765 #endif
766
767 /*
768 ** FOR NOW...SIMPLE EXIT
769 */
770 exit(1);
771 }
772
773 /*****************************
774 ** STOPWATCH ROUTINES **
775 *****************************/
776
777 /****************************
778 ** StartStopwatch
779 ** Starts a software stopwatch. Returns the first value of
780 ** the stopwatch in ticks.
781 */
StartStopwatch()782 unsigned long StartStopwatch()
783 {
784 #ifdef MACTIMEMGR
785 /*
786 ** For Mac code warrior, use timer. In this case, what we return is really
787 ** a dummy value.
788 */
789 InsTime((QElemPtr)&myTMTask);
790 PrimeTime((QElemPtr)&myTMTask,-MacHSTdelay);
791 return((unsigned long)1);
792 #else
793 #ifdef WIN31TIMER
794 /*
795 ** Win 3.x timer returns a DWORD, which we coax into a long.
796 */
797 _Call16(lpfn,"p",&win31tinfo);
798 return((unsigned long)win31tinfo.dwmsSinceStart);
799 #else
800 return((unsigned long)clock());
801 #endif
802 #endif
803 }
804
805 /****************************
806 ** StopStopwatch
807 ** Stops the software stopwatch. Expects as an input argument
808 ** the stopwatch start time.
809 */
StopStopwatch(unsigned long startticks)810 unsigned long StopStopwatch(unsigned long startticks)
811 {
812
813 #ifdef MACTIMEMGR
814 /*
815 ** For Mac code warrior...ignore startticks. Return val. in microseconds
816 */
817 RmvTime((QElemPtr)&myTMTask);
818 return((unsigned long)(MacHSTdelay+myTMTask.tmCount-MacHSTohead));
819 #else
820 #ifdef WIN31TIMER
821 _Call16(lpfn,"p",&win31tinfo);
822 return((unsigned long)win31tinfo.dwmsSinceStart-startticks);
823 #else
824 return((unsigned long)clock()-startticks);
825 #endif
826 #endif
827 }
828
829 /****************************
830 ** TicksToSecs
831 ** Converts ticks to seconds. Converts ticks to integer
832 ** seconds, discarding any fractional amount.
833 */
TicksToSecs(unsigned long tickamount)834 unsigned long TicksToSecs(unsigned long tickamount)
835 {
836 #ifdef CLOCKWCT
837 return((unsigned long)(tickamount/CLK_TCK));
838 #endif
839
840 #ifdef MACTIMEMGR
841 /* +++ MAC time manager version (using timer in microseconds) +++ */
842 return((unsigned long)(tickamount/1000000));
843 #endif
844
845 #ifdef CLOCKWCPS
846 /* Everybody else */
847 return((unsigned long)(tickamount/CLOCKS_PER_SEC));
848 #endif
849
850 #ifdef WIN31TIMER
851 /* Each tick is 840 nanoseconds */
852 return((unsigned long)(tickamount/1000L));
853 #endif
854
855 }
856
857 /****************************
858 ** TicksToFracSecs
859 ** Converts ticks to fractional seconds. In other words,
860 ** this returns the exact conversion from ticks to
861 ** seconds.
862 */
TicksToFracSecs(unsigned long tickamount)863 double TicksToFracSecs(unsigned long tickamount)
864 {
865 #ifdef CLOCKWCT
866 return((double)tickamount/(double)CLK_TCK);
867 #endif
868
869 #ifdef MACTIMEMGR
870 /* +++ MAC time manager version +++ */
871 return((double)tickamount/(double)1000000);
872 #endif
873
874 #ifdef CLOCKWCPS
875 /* Everybody else */
876 return((double)tickamount/(double)CLOCKS_PER_SEC);
877 #endif
878
879 #ifdef WIN31TIMER
880 /* Using 840 nanosecond ticks */
881 return((double)tickamount/(double)1000);
882 #endif
883 }
884
885