home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / bytewarp.zip / SYSSPEC.C < prev    next >
C/C++ Source or Header  |  1995-11-30  |  17KB  |  761 lines

  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. */
  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. true_addr=(ulong)returnval;
  135. if(global_align==0)
  136. {    adj_addr=true_addr;
  137.     if(AddMemArray(true_addr, adj_addr))
  138.         *errorcode=ERROR_MEMARRAY_FULL;
  139.     return(returnval);
  140. }
  141.  
  142. if(global_align==1)
  143. {    if(true_addr%2==0) adj_addr=true_addr+1;
  144. }
  145. else
  146. {    adj_addr=true_addr;
  147.     while(adj_addr%global_align!=0) ++adj_addr;
  148.     if(adj_addr%(global_align*2)==0) adj_addr+=global_align;
  149. }
  150. returnval=(void *)adj_addr;
  151. if(AddMemArray(true_addr,adj_addr))
  152.     *errorcode=ERROR_MEMARRAY_FULL;
  153. return(returnval);
  154. #endif
  155.  
  156. }
  157.  
  158.  
  159. /****************************
  160. ** FreeMemory
  161. ** This is the reverse of AllocateMemory.  The memory
  162. ** block passed in is freed.  Should an error occur,
  163. ** that error is returned in errorcode.
  164. */
  165. void FreeMemory(farvoid *mempointer,    /* Pointer to memory block */
  166.         int *errorcode)
  167. {
  168. #ifdef DOS16MEM
  169. /*
  170. ** 16-bit DOS VERSION!!
  171. */
  172. unsigned int segment;
  173. unsigned int offset;
  174. union REGS registers;
  175. struct SREGS sregisters;
  176.  
  177. /*
  178. ** First get the segment/offset of the farvoid pointer.
  179. */
  180. segment=FP_SEG(mempointer);
  181. offset=FP_OFF(mempointer);
  182.  
  183. /*
  184. ** Align the segment properly.  For as long as offset > 16,
  185. ** subtract 16 from offset and add 1 to segment.
  186. */
  187. while(offset>=16)
  188. {       offset-=16;
  189.     segment++;
  190. }
  191.  
  192. /*
  193. ** Build the call to DOS
  194. */
  195. registers.h.ah=0x49;            /* Free memory */
  196. sregisters.es=segment;
  197.  
  198. intdosx(®isters,®isters,&sregisters);
  199.  
  200. /*
  201. ** Check for error
  202. */
  203. if(registers.x.cflag)
  204. {       *errorcode=ERROR_MEMORY;
  205.     return;
  206. }
  207.  
  208. *errorcode=0;
  209. return;
  210. #endif
  211.  
  212. #ifdef MACMEM
  213. DisposPtr((Ptr)mempointer);
  214. *errorcode=0;
  215. return;
  216. #endif
  217.  
  218. #ifdef MALLOCMEM
  219. ulong adj_addr, true_addr;
  220.  
  221. /* Locate item in memory array */
  222. adj_addr=(ulong)mempointer;
  223. if(RemoveMemArray(adj_addr, &true_addr))
  224. {    *errorcode=ERROR_MEMARRAY_NFOUND;
  225.     return;
  226. }
  227. mempointer=(void *)true_addr;
  228. free(mempointer);
  229. *errorcode=0;
  230. return;
  231. #endif
  232. }
  233.  
  234. /****************************
  235. ** MoveMemory
  236. ** Moves n bytes from a to b.  Handles overlap.
  237. ** In most cases, this is just a memmove operation.
  238. ** But, not in DOS....noooo....
  239. */
  240. void MoveMemory( farvoid *destination,  /* Destination address */
  241.         farvoid *source,        /* Source address */
  242.         unsigned long nbytes)
  243. {
  244.  
  245. /* +++16-bit DOS VERSION+++ */
  246. #ifdef DOS16MEM
  247.  
  248.     FarDOSmemmove( destination, source, nbytes);
  249.  
  250. #else
  251.  
  252. memmove(destination, source, nbytes);
  253.  
  254. #endif
  255. }
  256.  
  257. #ifdef DOS16MEM
  258.  
  259. /****************************
  260. ** FarDOSmemmove
  261. ** Performs the same function as memmove for DOS when
  262. ** the arrays are defined with far pointers.
  263. */
  264. void FarDOSmemmove(farvoid *destination,        /* Destination pointer */
  265.         farvoid *source,        /* Source pointer */
  266.         unsigned long nbytes)   /* # of bytes to move */
  267. {
  268. unsigned char huge *uchsource;  /* Temp source */
  269. unsigned char huge *uchdest;    /* Temp destination */
  270. unsigned long saddr;            /* Source "true" address */
  271. unsigned long daddr;            /* Destination "true" address */
  272.  
  273.  
  274. /*
  275. ** Get unsigned char pointer equivalents
  276. */
  277. uchsource=(unsigned char huge *)source;
  278. uchdest=(unsigned char huge *)destination;
  279.  
  280. /*
  281. ** Calculate true address of source and destination and
  282. ** compare.
  283. */
  284. saddr=(unsigned long)(FP_SEG(source)*16 + FP_OFF(source));
  285. daddr=(unsigned long)(FP_SEG(destination)*16 + FP_OFF(destination));
  286.  
  287. if(saddr > daddr)
  288. {
  289.     /*
  290.     ** Source is greater than destination.
  291.     ** Use a series of standard move operations.
  292.     ** We'll move 65535 bytes at a time.
  293.     */
  294.     while(nbytes>=65535L)
  295.     {       _fmemmove((farvoid *)uchdest,
  296.             (farvoid *)uchsource,
  297.             (size_t) 65535);
  298.         uchsource+=65535;       /* Advance pointers */
  299.         uchdest+=65535;
  300.         nbytes-=65535;
  301.     }
  302.  
  303.     /*
  304.     ** Move remaining bytes
  305.     */
  306.     if(nbytes!=0L)
  307.         _fmemmove((farvoid *)uchdest,
  308.             (farvoid *)uchsource,
  309.             (size_t)(nbytes & 0xFFFF));
  310.  
  311. }
  312. else
  313. {
  314.     /*
  315.     ** Destination is greater than source.
  316.     ** Advance pointers to the end of their
  317.     ** respective blocks.
  318.     */
  319.     uchsource+=nbytes;
  320.     uchdest+=nbytes;
  321.  
  322.     /*
  323.     ** Again, move 65535 bytes at a time.  However,
  324.     ** "back" the pointers up before doing the
  325.     ** move.
  326.     */
  327.     while(nbytes>=65535L)
  328.     {
  329.         uchsource-=65535;
  330.         uchdest-=65535;
  331.         _fmemmove((farvoid *)uchdest,
  332.             (farvoid *)uchsource,
  333.             (size_t) 65535);
  334.         nbytes-=65535;
  335.     }
  336.  
  337.     /*
  338.     ** Move remaining bytes.
  339.     */
  340.     if(nbytes!=0L)
  341.     {       uchsource-=nbytes;
  342.         uchdest-=nbytes;
  343.         _fmemmove((farvoid *)uchdest,
  344.             (farvoid *)uchsource,
  345.             (size_t)(nbytes & 0xFFFF));
  346.     }
  347. }
  348. return;
  349. }
  350. #endif
  351.  
  352. /***********************************
  353. ** MEMORY ARRAY HANDLING ROUTINES **
  354. ***********************************/
  355. /****************************
  356. ** InitMemArray
  357. ** Initialize the memory array.  This simply amounts to
  358. ** setting mem_array_ents to zero, indicating that there
  359. ** isn't anything in the memory array.
  360. */
  361. void InitMemArray(void)
  362. {
  363. mem_array_ents=0;
  364. return;
  365. }
  366.  
  367. /***************************
  368. ** AddMemArray
  369. ** Add a pair of items to the memory array.
  370. **  true_addr is the true address (mem_array[0][n])
  371. **  adj_addr is the adjusted address (mem_array[0][n])
  372. ** Returns 0 if ok
  373. ** -1 if not enough room
  374. */
  375. int AddMemArray(ulong true_addr,
  376.         ulong adj_addr)
  377. {
  378. if(mem_array_ents>=MEM_ARRAY_SIZE)
  379.     return(-1);
  380.  
  381. mem_array[0][mem_array_ents]=true_addr;
  382. mem_array[1][mem_array_ents]=adj_addr;
  383. mem_array_ents++;
  384. return(0);
  385. }
  386.  
  387. /*************************
  388. ** RemoveMemArray
  389. ** Given an adjusted address value (mem_array[1][n]), locate
  390. ** the entry and remove it from the mem_array.
  391. ** Also returns the associated true address.
  392. ** Returns 0 if ok
  393. ** -1 if not found.
  394. */
  395. int RemoveMemArray(ulong adj_addr,ulong *true_addr)
  396. {
  397. int i,j;
  398.  
  399. /* Locate the item in the array. */
  400. for(i=0;i<mem_array_ents;i++)
  401.     if(mem_array[1][i]==adj_addr)
  402.     {       /* Found it..bubble stuff down */
  403.         *true_addr=mem_array[0][i];
  404.         j=i;
  405.         while(j+1<mem_array_ents)
  406.         {       mem_array[0][j]=mem_array[0][j+1];
  407.             mem_array[1][j]=mem_array[1][j+1];
  408.             j++;
  409.         }
  410.         mem_array_ents--;
  411.         return(0);      /* Return if found */
  412.     }
  413.  
  414. /* If we made it here...something's wrong...show error */
  415. return(-1);
  416. }
  417.  
  418. /**********************************
  419. **    FILE HANDLING ROUTINES     **
  420. **********************************/
  421.  
  422. /****************************
  423. ** CreateFile
  424. ** This routine accepts a filename for an argument and
  425. ** creates that file in the current directory (unless the
  426. ** name contains a path that overrides the current directory).
  427. ** Note that the routine does not OPEN the file.
  428. ** If the file exists, it is truncated to length 0.
  429. */
  430. void CreateFile(char *filename,
  431.         int *errorcode)
  432. {
  433.  
  434. #ifdef DOS16
  435. /*
  436. ** DOS VERSION!!
  437. */
  438. int fhandle;            /* File handle used internally */
  439.  
  440. fhandle=open(filename,O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
  441.  
  442. if(fhandle==-1)
  443.     *errorcode=ERROR_FILECREATE;
  444. else
  445.     *errorcode=0;
  446.  
  447. /*
  448. ** Since all we're doing here is creating the file,
  449. ** go ahead and close it.
  450. */
  451. close(fhandle);
  452.  
  453. return;
  454. #endif
  455. }
  456.  
  457. /****************************
  458. ** bmOpenFile
  459. ** Opens the file given by fname, returning its handle.
  460. ** If an error occurs, returns its code in errorcode.
  461. ** The file is opened in read-write exclusive mode.
  462. */
  463. int bmOpenFile(char *fname,       /* File name */
  464.     int *errorcode)         /* Error code returned */
  465. {
  466.  
  467. #ifdef DOS16
  468. /*
  469. ** DOS VERSION!!
  470. */
  471. int fhandle;            /* Returned file handle */
  472.  
  473. fhandle=open(fname,O_BINARY | O_RDWR, S_IREAD | S_IWRITE);
  474.  
  475. if(fhandle==-1)
  476.     *errorcode=ERROR_FILEOPEN;
  477. else
  478.     *errorcode=0;
  479.  
  480. return(fhandle);
  481. #endif
  482.  
  483. }
  484.  
  485. /****************************
  486. ** CloseFile
  487. ** Closes the file identified by fhandle.
  488. ** A more inocuous routine there never was.
  489. */
  490. void CloseFile(int fhandle,             /* File handle */
  491.         int *errorcode)         /* Returned error code */
  492. {
  493.  
  494. #ifdef DOS16
  495. /*
  496. ** DOS VERSION!!!
  497. */
  498. close(fhandle);
  499. *errorcode=0;
  500. return;
  501. #endif
  502.  
  503. }
  504.  
  505. /****************************
  506. ** readfile
  507. ** Read bytes from an opened file.  This routine
  508. ** is a combination seek-and-read.
  509. ** Note that this routine expects the offset to be from
  510. ** the beginning of the file.
  511. */
  512. void readfile(int fhandle,              /* File handle */
  513.     unsigned long offset,           /* Offset into file */
  514.     unsigned long nbytes,           /* # of bytes to read */
  515.     void *buffer,                   /* Buffer to read into */
  516.     int *errorcode)                 /* Returned error code */
  517. {
  518.  
  519. #ifdef DOS16
  520. /*
  521. ** DOS VERSION!!
  522. */
  523.  
  524. long newoffset;                         /* New offset by lseek */
  525. int readcode;                           /* Return code from read */
  526.  
  527. /*
  528. ** Presume success.
  529. */
  530. *errorcode=0;
  531.  
  532. /*
  533. ** Seek to the proper offset.
  534. */
  535. newoffset=lseek(fhandle,(long)offset,SEEK_SET);
  536. if(newoffset==-1L)
  537. {       *errorcode=ERROR_FILESEEK;
  538.     return;
  539. }
  540.  
  541. /*
  542. ** Do the read.
  543. */
  544. readcode=read(fhandle,buffer,(unsigned)(nbytes & 0xFFFF));
  545. if(readcode==-1)
  546.     *errorcode=ERROR_FILEREAD;
  547.  
  548. return;
  549. #endif
  550.  
  551. }
  552.  
  553. /****************************
  554. ** writefile
  555. ** writes bytes to an opened file.  This routine is
  556. ** a combination seek-and-write.
  557. ** Note that this routine expects the offset to be from
  558. ** the beinning of the file.
  559. */
  560. void writefile(int fhandle,             /* File handle */
  561.     unsigned long offset,           /* Offset into file */
  562.     unsigned long nbytes,           /* # of bytes to read */
  563.     void *buffer,                   /* Buffer to read into */
  564.     int *errorcode)                 /* Returned error code */
  565. {
  566.  
  567. #ifdef DOS16
  568. /*
  569. ** DOS VERSION!!
  570. */
  571.  
  572. long newoffset;                         /* New offset by lseek */
  573. int writecode;                          /* Return code from write */
  574.  
  575. /*
  576. ** Presume success.
  577. */
  578. *errorcode=0;
  579.  
  580. /*
  581. ** Seek to the proper offset.
  582. */
  583. newoffset=lseek(fhandle,(long)offset,SEEK_SET);
  584. if(newoffset==-1L)
  585. {       *errorcode=ERROR_FILESEEK;
  586.     return;
  587. }
  588.  
  589. /*
  590. ** Do the write.
  591. */
  592. writecode=write(fhandle,buffer,(unsigned)(nbytes & 0xFFFF));
  593. if(writecode==-1)
  594.     *errorcode=ERROR_FILEWRITE;
  595.  
  596. return;
  597. #endif
  598.  
  599. }
  600.  
  601. /********************************
  602. **   ERROR HANDLING ROUTINES   **
  603. ********************************/
  604.  
  605. /****************************
  606. ** ReportError
  607. ** Report error message condition.
  608. */
  609. void ReportError(char *errorcontext,    /* Error context string */
  610.         int errorcode)          /* Error code number */
  611. {
  612.  
  613. /*
  614. ** Display error context
  615. */
  616. printf("ERROR CONDITION\nContext: %s\n",errorcontext);
  617.  
  618. /*
  619. ** Display code
  620. */
  621. printf("Code: %d",errorcode);
  622.  
  623. return;
  624. }
  625.  
  626. /****************************
  627. ** ErrorExit
  628. ** Peforms an exit from an error condition.
  629. */
  630. void ErrorExit()
  631. {
  632.  
  633. /*
  634. ** For profiling on the Mac with MetroWerks -- 11/17/94 RG
  635. ** Have to do this to turn off profiler.
  636. */
  637. #ifdef MACCWPROF
  638. #if __profile__
  639. ProfilerTerm();
  640. #endif
  641. #endif
  642.  
  643. /*
  644. ** FOR NOW...SIMPLE EXIT
  645. */
  646. exit(1);
  647. }
  648.  
  649. /*****************************
  650. **    STOPWATCH ROUTINES    **
  651. *****************************/
  652.  
  653. /****************************
  654. ** StartStopwatch
  655. ** Starts a software stopwatch.  Returns the first value of
  656. ** the stopwatch in ticks.
  657. */
  658. unsigned long StartStopwatch()
  659. {
  660. #ifdef MACTIMEMGR
  661. /*
  662. ** For Mac code warrior, use timer. In this case, what we return is really
  663. ** a dummy value.
  664. */
  665. InsTime((QElemPtr)&myTMTask);
  666. PrimeTime((QElemPtr)&myTMTask,-MacHSTdelay);
  667. return((unsigned long)1);
  668. #else
  669. #ifdef WIN31TIMER
  670. /*
  671. ** Win 3.x timer returns a DWORD, which we coax into a long.
  672. */
  673. _Call16(lpfn,"p",&win31tinfo);
  674. return((unsigned long)win31tinfo.dwmsSinceStart);
  675. #else
  676. return((unsigned long)clock());
  677. #endif
  678. #endif
  679. }
  680.  
  681. /****************************
  682. ** StopStopwatch
  683. ** Stops the software stopwatch.  Expects as an input argument
  684. ** the stopwatch start time.
  685. */
  686. unsigned long StopStopwatch(unsigned long startticks)
  687. {
  688.     
  689. #ifdef MACTIMEMGR
  690. /*
  691. ** For Mac code warrior...ignore startticks.  Return val. in microseconds
  692. */
  693. RmvTime((QElemPtr)&myTMTask);
  694. return((unsigned long)(MacHSTdelay+myTMTask.tmCount-MacHSTohead));
  695. #else
  696. #ifdef WIN31TIMER
  697. _Call16(lpfn,"p",&win31tinfo);
  698. return((unsigned long)win31tinfo.dwmsSinceStart-startticks);
  699. #else
  700. return((unsigned long)clock()-startticks);
  701. #endif
  702. #endif
  703. }
  704.  
  705. /****************************
  706. ** TicksToSecs
  707. ** Converts ticks to seconds.  Converts ticks to integer
  708. ** seconds, discarding any fractional amount.
  709. */
  710. unsigned long TicksToSecs(unsigned long tickamount)
  711. {
  712. #ifdef CLOCKWCT
  713. return((unsigned long)(tickamount/CLK_TCK));
  714. #endif
  715.  
  716. #ifdef MACTIMEMGR
  717. /* +++ MAC time manager version (using timer in microseconds) +++ */
  718. return((unsigned long)(tickamount/1000000));
  719. #endif
  720.  
  721. #ifdef CLOCKWCPS
  722. /* Everybody else */
  723. return((unsigned long)(tickamount/CLOCKS_PER_SEC));
  724. #endif
  725.  
  726. #ifdef WIN31TIMER
  727. /* Each tick is 840 nanoseconds */
  728. return((unsigned long)(tickamount/1000L));
  729. #endif
  730.  
  731. }
  732.  
  733. /****************************
  734. ** TicksToFracSecs
  735. ** Converts ticks to fractional seconds.  In other words,
  736. ** this returns the exact conversion from ticks to
  737. ** seconds.
  738. */
  739. double TicksToFracSecs(unsigned long tickamount)
  740. {
  741. #ifdef CLOCKWCT
  742. return((double)tickamount/(double)CLK_TCK);
  743. #endif
  744.  
  745. #ifdef MACTIMEMGR
  746. /* +++ MAC time manager version +++ */
  747. return((double)tickamount/(double)1000000);
  748. #endif
  749.  
  750. #ifdef CLOCKWCPS
  751. /* Everybody else */
  752. return((double)tickamount/(double)CLOCKS_PER_SEC);
  753. #endif
  754.  
  755. #ifdef WIN31TIMER
  756. /* Using 840 nanosecond ticks */
  757. return((double)tickamount/(double)1000);
  758. #endif
  759. }
  760.  
  761.