home *** CD-ROM | disk | FTP | other *** search
- /* diskio.c - disk benchmark
- *
- * Author: Kai Uwe Rommel <rommel@ars.muc.de>
- * Created: Fri Jul 08 1994
- */
-
- static char *rcsid =
- "$Id: diskio.c,v 1.11 1997/02/09 15:06:38 rommel Exp rommel $";
- static char *rcsrev = "$Revision: 1.11 $";
-
- /*
- * $Log: diskio.c,v $
- * Revision 1.11 1997/02/09 15:06:38 rommel
- * changed command line interface
- *
- * Revision 1.10 1997/01/12 21:15:10 rommel
- * added CD-ROM benchmarks
- *
- * Revision 1.9 1995/12/31 20:24:09 rommel
- * Changed CPU load calculation
- * General cleanup
- *
- * Revision 1.8 1995/12/28 11:28:07 rommel
- * Fixed async timer problem.
- *
- * Revision 1.7 1995/12/28 10:04:15 rommel
- * Added CPU benchmark (concurrently to disk I/O)
- *
- * Revision 1.6 1995/11/24 16:02:10 rommel
- * Added bus/drive cache speed test by
- * repeatedly reading a small amount of data
- *
- * Revision 1.5 1995/08/09 13:07:02 rommel
- * Changes for new diskacc2 library, minor corrections, arguments.
- *
- * Revision 1.4 1994/07/11 14:23:00 rommel
- * Changed latency timing
- *
- * Revision 1.3 1994/07/09 13:07:20 rommel
- * Changed transfer speed test
- *
- * Revision 1.2 1994/07/08 21:53:05 rommel
- * Cleanup
- *
- * Revision 1.1 1994/07/08 21:29:41 rommel
- * Initial revision
- *
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #define INCL_DOS
- #define INCL_DOSDEVICES
- #define INCL_DOSDEVIOCTL
- #define INCL_DOSERRORS
- #define INCL_NOPM
- #include <os2.h>
-
- #include "diskacc2.h"
-
- #define INTERVAL 10
-
- #define THREADSTACK 65536
-
- char *pBuffer;
-
- int time_over;
- long dhry_time, dhry_result;
-
- extern unsigned long Number_Of_Runs;
- extern long dhry_stone(void);
-
- VOID APIENTRY timer_thread(ULONG nArg)
- {
- HEV hSem;
- HTIMER hTimer;
-
- // DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0);
-
- DosCreateEventSem(0, &hSem, DC_SEM_SHARED, 0);
-
- DosAsyncTimer(nArg * 1000, (HSEM) hSem, &hTimer);
- DosWaitEventSem(hSem, SEM_INDEFINITE_WAIT);
- DosStopTimer(hTimer);
-
- DosCloseEventSem(hSem);
-
- time_over = 1;
- Number_Of_Runs = 0;
-
- DosExit(EXIT_THREAD, 0);
- }
-
- int start_alarm(ULONG nSeconds)
- {
- TID ttid;
-
- time_over = 0;
- Number_Of_Runs = -1;
-
- if (DosCreateThread(&ttid, timer_thread, nSeconds, 0, THREADSTACK))
- return printf("Cannot create timer thread.\n"), -1;
-
- return 0;
- }
-
- int start_timer(QWORD *nStart)
- {
- if (DosTmrQueryTime(nStart))
- return printf("Timer error.\n"), -1;
-
- return 0;
- }
-
- int stop_timer(QWORD *nStart, int accuracy)
- {
- QWORD nStop;
- ULONG nFreq;
-
- if (DosTmrQueryTime(&nStop))
- return printf("Timer error.\n"), -1;
- if (DosTmrQueryFreq(&nFreq))
- return printf("Timer error.\n"), -1;
-
- nFreq = (nFreq + accuracy / 2) / accuracy;
-
- return (nStop.ulLo - nStart->ulLo) / nFreq;
- }
-
- VOID APIENTRY dhry_thread(ULONG nArg)
- {
- DosSetPriority(PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MAXIMUM, 0);
-
- dhry_time = dhry_stone();
-
- DosExit(EXIT_THREAD, 0);
- }
-
- int bench_hd_bus(int nHandle, unsigned nSectors)
- {
- int nCnt, nData = 0, nTime;
- QWORD nLocal;
-
- printf("Drive cache/bus transfer rate: ");
- fflush(stdout);
-
- if (start_alarm(INTERVAL))
- return -1;
-
- if (start_timer(&nLocal))
- return -1;
-
- for (nCnt = 0; !time_over; nCnt++)
- {
- if (DskRead(nHandle, 0, 0, 1, nSectors, pBuffer))
- return printf("Disk read error.\n"), -1;
-
- nData += nSectors * 512;
- }
-
- if ((nTime = stop_timer(&nLocal, 1024)) == -1)
- return -1;
-
- printf("%d k/sec\n", nData / nTime);
-
- return 0;
- }
-
- int bench_hd_transfer(int nHandle, int nTrack, int nDirection,
- unsigned nSides, unsigned nSectors)
- {
- int nCnt, nData = 0, nTime;
- QWORD nLocal;
-
- printf("Data transfer rate on track %-4d: ", nTrack);
- fflush(stdout);
-
- if (start_alarm(INTERVAL))
- return -1;
-
- if (start_timer(&nLocal))
- return -1;
-
- for (nCnt = 0; !time_over; nCnt++)
- {
- if (DskRead(nHandle, nCnt % nSides,
- nTrack + (nCnt / nSides) * nDirection, 1, nSectors, pBuffer))
- return printf("Disk read error.\n"), -1;
-
- nData += nSectors * 512;
- }
-
- if ((nTime = stop_timer(&nLocal, 1024)) == -1)
- return -1;
-
- printf("%d k/sec\n", nData / nTime);
-
- return 0;
- }
-
- int bench_hd_cpuusage(int nHandle, unsigned nSides, unsigned nSectors)
- {
- int nCnt, nData = 0, nTime, nPercent;
- QWORD nLocal;
- TID dtid;
- APIRET rc;
-
- printf("CPU usage by full speed disk transfers: ");
- fflush(stdout);
-
- if (start_alarm(INTERVAL))
- return -1;
-
- if (DosCreateThread(&dtid, dhry_thread, 0, 0, THREADSTACK))
- return -1;
-
- if (start_timer(&nLocal))
- return -1;
-
- for (nCnt = 0; !time_over; nCnt++)
- {
- if (DskRead(nHandle, nCnt % nSides, nCnt / nSides, 1, nSectors, pBuffer))
- return printf("Disk read error.\n"), -1;
-
- nData += nSectors * 512;
- }
-
- if ((nTime = stop_timer(&nLocal, 1024)) == -1)
- return -1;
-
- if ((rc = DosWaitThread(&dtid, DCWW_WAIT)) && rc != ERROR_INVALID_THREADID)
- return -1; /* it may have already terminated */
-
- if (dhry_result == 0)
- dhry_result = 1; /* to avoid dividing by zero */
-
- dhry_time = (dhry_time + 500) / 1000;
- nPercent = (dhry_result - Number_Of_Runs / dhry_time) * 100 / dhry_result;
-
- printf("%d%%\n", nPercent);
-
- return 0;
- }
-
- int bench_hd_latency(int nHandle, unsigned nSectors)
- {
- int nCnt, nSector, nTime;
- QWORD nLocal;
-
- printf("Average latency time: ");
- fflush(stdout);
-
- srand(1);
-
- if (start_alarm(INTERVAL))
- return -1;
-
- if (start_timer(&nLocal))
- return -1;
-
- for (nCnt = 0; !time_over; nCnt++)
- {
- nSector = rand() * nSectors / RAND_MAX + 1;
-
- if (DskRead(nHandle, 0, 0, nSector, 1, pBuffer))
- return printf("Disk read error.\n"), -1;
- }
-
- if ((nTime = stop_timer(&nLocal, 1000)) == -1)
- return -1;
-
- nTime = nTime * 10 / nCnt;
-
- printf("%d.%d ms\n", nTime / 10, nTime % 10);
-
- return nTime;
- }
-
- int bench_hd_seek(int nHandle, unsigned nSides, unsigned nSectors, unsigned nTracks)
- {
- int nCnt, nSide, nTrack, nSector, nTime;
- QWORD nLocal;
-
- printf("Average data access time: ");
- fflush(stdout);
-
- srand(1);
-
- if (start_alarm(INTERVAL))
- return -1;
-
- if (start_timer(&nLocal))
- return -1;
-
- for (nCnt = 0; !time_over; nCnt++)
- {
- nSide = rand() * nSides / RAND_MAX;
- nSector = rand() * nSectors / RAND_MAX;
- nTrack = rand() * nTracks / RAND_MAX;
-
- if (DskRead(nHandle, nSide, nTrack, nSector, 1, pBuffer))
- return printf("Disk read error.\n"), -1;
- }
-
- if ((nTime = stop_timer(&nLocal, 1000)) == -1)
- return -1;
-
- nTime = nTime * 10 / nCnt;
-
- printf("%d.%d ms\n", nTime / 10, nTime % 10);
-
- return 0;
- }
-
- int bench_hd(int nDisk)
- {
- int nHandle;
- unsigned nSides, nTracks, nSectors;
- char szName[8];
-
- sprintf(szName, "$%d:", nDisk);
-
- if ((nHandle = DskOpen(szName, 0, 0, &nSides, &nTracks, &nSectors)) < 0)
- return printf("\nCannot access disk %d.\n", nDisk), -1;
-
- printf("\nHard disk %d: %d sides, %d cylinders, %d sectors per track = %d MB\n",
- nDisk, nSides, nTracks, nSectors,
- nSides * nTracks * nSectors / 2048);
-
- if ((pBuffer = malloc(nSectors * 512)) == NULL)
- return printf("\nNot enough memory.\n"), -1;
-
- bench_hd_bus(nHandle, nSectors);
- bench_hd_transfer(nHandle, 0, 1, nSides, nSectors);
- bench_hd_transfer(nHandle, nTracks - 1, -1, nSides, nSectors);
- bench_hd_cpuusage(nHandle, nSides, nSectors);
- bench_hd_latency(nHandle, nSectors);
- bench_hd_seek(nHandle, nSides, nSectors, nTracks);
-
- free(pBuffer);
- DskClose(nHandle);
-
- return 0;
- }
-
- int bench_cd_transfer(int nHandle)
- {
- int nCnt, nData = 0, nTime, nRate;
- QWORD nLocal;
-
- printf("Data transfer rate: ");
- fflush(stdout);
-
- if (start_alarm(INTERVAL))
- return -1;
-
- if (start_timer(&nLocal))
- return -1;
-
- for (nCnt = 0; !time_over; nCnt++)
- {
- if (CDRead(nHandle, nCnt * 32, 32, pBuffer) == -1)
- return printf("CD-ROM read error.\n"), -1;
-
- nData += 32 * 2048;
- }
-
- if ((nTime = stop_timer(&nLocal, 1024)) == -1)
- return -1;
-
- nRate = nData / nTime;
- printf("%d k/sec (~%.1fx)\n", nRate, (double) nRate / 150.0);
-
- return 0;
- }
-
- int bench_cd_cpuusage(int nHandle)
- {
- int nCnt, nData = 0, nTime, nPercent;
- QWORD nLocal;
- TID dtid;
- APIRET rc;
-
- printf("CPU usage by full speed CD-ROM reads: ");
- fflush(stdout);
-
- if (start_alarm(INTERVAL))
- return -1;
-
- if (DosCreateThread(&dtid, dhry_thread, 0, 0, THREADSTACK))
- return -1;
-
- if (start_timer(&nLocal))
- return -1;
-
- for (nCnt = 0; !time_over; nCnt++)
- {
- if (CDRead(nHandle, nCnt * 32, 32, pBuffer) == -1)
- return printf("CD-ROM read error.\n"), -1;
-
- nData += 32 * 2048;
- }
-
- if ((nTime = stop_timer(&nLocal, 1024)) == -1)
- return -1;
-
- if ((rc = DosWaitThread(&dtid, DCWW_WAIT)) && rc != ERROR_INVALID_THREADID)
- return -1; /* it may have already terminated */
-
- if (dhry_result == 0)
- dhry_result = 1; /* to avoid dividing by zero */
-
- dhry_time = (dhry_time + 500) / 1000;
- nPercent = (dhry_result - Number_Of_Runs / dhry_time) * 100 / dhry_result;
-
- printf("%d%%\n", nPercent);
-
- return 0;
- }
-
- int bench_cd_seek(int nHandle, unsigned nSectors)
- {
- int nCnt, nSector, nTime;
- QWORD nLocal;
-
- printf("Average data access time: ");
- fflush(stdout);
-
- srand(1);
-
- if (start_alarm(INTERVAL))
- return -1;
-
- if (start_timer(&nLocal))
- return -1;
-
- for (nCnt = 0; !time_over; nCnt++)
- {
- nSector = (nSectors * 1000) / RAND_MAX;
- nSector = nSector * rand() / 1000;
-
- if (CDRead(nHandle, nSector, 1, pBuffer) != 1)
- return printf("CD-ROM read error.\n"), -1;
- }
-
- if ((nTime = stop_timer(&nLocal, 1000)) == -1)
- return -1;
-
- nTime = nTime * 10 / nCnt;
-
- printf("%d.%d ms\n", nTime / 10, nTime % 10);
-
- return 0;
- }
-
- int bench_cd(int nDrive)
- {
- int nHandle, nDriveLetter;
- unsigned nSectors;
- char szDrive[3], szUPC[8];
-
- if ((nDriveLetter = CDFind(nDrive)) == -1)
- return printf("\nCannot access CD-ROM drive %d.\n", nDrive), -1;
-
- szDrive[0] = (char) nDriveLetter;
- szDrive[1] = ':';
- szDrive[2] = 0;
-
- if ((nHandle = CDOpen(szDrive, 1, szUPC, &nSectors)) == -1)
- return -1;
-
- printf("\nCD-ROM drive %s %d sectors = %d MB\n",
- szDrive, nSectors, nSectors / 512);
-
- if ((pBuffer = malloc(32 * 2048)) == NULL)
- return printf("\nNot enough memory.\n"), -1;
-
- /* spin up and seek to first sector */
- if (CDRead(nHandle, 0, 32, pBuffer) == -1)
- return printf("CD-ROM read error.\n"), -1;
-
- bench_cd_transfer(nHandle);
- bench_cd_cpuusage(nHandle);
- bench_cd_seek(nHandle, nSectors);
-
- free(pBuffer);
- CDClose(nHandle);
-
- return 0;
- }
-
- typedef struct
- {
- int nHandle, nData;
- unsigned nSides, nSectors, nTracks;
- void *pBuffer;
- }
- THREADPARMS;
-
- VOID APIENTRY bench_concurrent_hd(ULONG nArg)
- {
- THREADPARMS *ptr = (THREADPARMS *) nArg;
- int nCnt;
-
- for (nCnt = 0; !time_over; nCnt++)
- {
- if (DskRead(ptr->nHandle, nCnt % ptr->nSides, nCnt / ptr->nSides, 1,
- ptr->nSectors, ptr->pBuffer))
- {
- printf("Disk read error.\n");
- break;
- }
-
- ptr->nData += ptr->nSectors * 512;
- }
-
- DosExit(EXIT_THREAD, 0);
- }
-
- VOID APIENTRY bench_concurrent_cd(ULONG nArg)
- {
- THREADPARMS *ptr = (THREADPARMS *) nArg;
- int nCnt;
-
- for (nCnt = 0; !time_over; nCnt++)
- {
- if (CDRead(ptr->nHandle, nCnt * 32, 32, ptr->pBuffer) == -1)
- {
- printf("CD-ROM read error.\n");
- break;
- }
-
- ptr->nData += 32 * 2048;
- }
-
- DosExit(EXIT_THREAD, 0);
- }
-
- int bench_concurrent(int nDisk, int nCD)
- {
- int nDriveLetter, nTime, nPercent;
- char szDrive[3], szUPC[8], szName[8];
- THREADPARMS tHD, tCD;
- TID tidHD, tidCD;
- QWORD nLocal;
- APIRET rc;
-
- sprintf(szName, "$%d:", nDisk);
-
- if ((tHD.nHandle = DskOpen(szName, 0, 0,
- &tHD.nSides, &tHD.nTracks, &tHD.nSectors)) < 0)
- return printf("\nCannot access disk %d.\n", nDisk), -1;
-
- if ((tHD.pBuffer = malloc(tHD.nSectors * 512)) == NULL)
- return printf("\nNot enough memory.\n"), -1;
-
- if ((nDriveLetter = CDFind(nCD)) == -1)
- return printf("\nCannot access CD-ROM drive %d.\n", nCD), -1;
-
- szDrive[0] = (char) nDriveLetter;
- szDrive[1] = ':';
- szDrive[2] = 0;
-
- if ((tCD.nHandle = CDOpen(szDrive, 1, szUPC, &tCD.nSectors)) == -1)
- return -1;
-
- if ((tCD.pBuffer = malloc(32 * 2048)) == NULL)
- return printf("\nNot enough memory.\n"), -1;
-
- /* spin up and seek to first sector */
- if (CDRead(tCD.nHandle, 0, 32, tCD.pBuffer) == -1)
- return printf("CD-ROM read error.\n"), -1;
-
- printf("\nConcurrent hard disk %d and CD-ROM %d reads at full speed:", nDisk, nCD);
- fflush(stdout);
- tHD.nData = tCD.nData = 0;
-
- if (start_alarm(INTERVAL))
- return -1;
-
- if (start_timer(&nLocal))
- return -1;
-
- if (DosCreateThread(&tidHD, bench_concurrent_hd, (ULONG) &tHD, 0, THREADSTACK))
- return -1;
- if (DosCreateThread(&tidCD, bench_concurrent_cd, (ULONG) &tCD, 0, THREADSTACK))
- return -1;
-
- DosSetPriority(PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MAXIMUM, 0);
- dhry_time = dhry_stone();
- DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MINIMUM, 0);
-
- if ((rc = DosWaitThread(&tidHD, DCWW_WAIT)) && rc != ERROR_INVALID_THREADID)
- return -1; /* it may have already terminated */
- if ((rc = DosWaitThread(&tidCD, DCWW_WAIT)) && rc != ERROR_INVALID_THREADID)
- return -1; /* it may have already terminated */
-
- if ((nTime = stop_timer(&nLocal, 1024)) == -1)
- return -1;
-
- if (dhry_result == 0)
- dhry_result = 1; /* to avoid dividing by zero */
-
- dhry_time = (dhry_time + 500) / 1000;
- nPercent = (dhry_result - Number_Of_Runs / dhry_time) * 100 / dhry_result;
-
- printf("\nHard disk throughput: %d k/sec\n", tHD.nData / nTime);
- printf("CD-ROM throughput: %d k/sec\n", tCD.nData / nTime);
- printf("CPU usage: %d%%\n", nPercent);
-
- free(tCD.pBuffer);
- CDClose(tCD.nHandle);
-
- free(tHD.pBuffer);
- DskClose(tHD.nHandle);
-
- return 0;
- }
-
- int bench_dhry(void)
- {
- printf("Dhrystone benchmark for this CPU: ");
- fflush(stdout);
-
- if (start_alarm(INTERVAL / 2))
- return -1;
-
- // DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MAXIMUM, 0);
- dhry_time = dhry_stone();
- // DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MINIMUM, 0);
-
- dhry_time = (dhry_time + 500) / 1000;
- dhry_result = Number_Of_Runs / dhry_time;
-
- printf("%d runs/sec\n", dhry_result);
-
- return 0;
- }
-
- int main(int argc, char **argv)
- {
- char szVersion[32];
- USHORT nDisks;
- int nCDROMs, nCount, xHD[26], xCD[26], cHD = 0, cCD = 0;
-
- strcpy(szVersion, rcsrev + sizeof("$Revision: ") - 1);
- *strchr(szVersion, ' ') = 0;
-
- printf("\nDISKIO - Fixed Disk Benchmark, Version %s"
- "\n(C) 1994-1997 Kai Uwe Rommel\n", szVersion);
-
- if (DosPhysicalDisk(INFO_COUNT_PARTITIONABLE_DISKS, &nDisks, sizeof(nDisks), 0, 0))
- return printf("\nCannot determine number of disks.\n"), 1;
-
- printf("\nNumber of fixed disks: %d\n", nDisks);
-
- nCDROMs = CDFind(0);
- printf("Number of CD-ROM drives: %d\n", nCDROMs);
-
- if (argc > 1)
- {
- nDisks = nCDROMs = 0;
-
- for (nCount = 1; nCount < argc; )
- if (stricmp(argv[nCount], "-hd") == 0)
- {
- for (nCount++; argv[nCount][0] != '-'; nCount++)
- xHD[nDisks++] = atoi(argv[nCount]);
- }
- else if (stricmp(argv[nCount], "-cd") == 0)
- {
- for (nCount++; argv[nCount][0] != '-'; nCount++)
- xCD[nCDROMs++] = atoi(argv[nCount]);
- }
- else if (stricmp(argv[nCount], "-c") == 0)
- {
- if (argv[nCount + 1][0] != '-' && argv[nCount + 2][0] != '-')
- {
- cHD = atoi(argv[nCount + 1]);
- cCD = atoi(argv[nCount + 2]);
- nCount += 3;
- }
- }
- else if (stricmp(argv[nCount], "-?") == 0)
- {
- printf("\nUsage:\tdiskio [options]\n"
- "\n\t-hd <list of hard disk numbers>"
- "\n\t-cd <list of CD-ROM drive numbers>"
- "\n\t-c <pair of hard disk and CD-ROM drive numbers>\n"
- "\nHard disk and CD-ROM drive numbers are physical ones and start at 1."
- "\nThe drive number lists must be blank separated.\n"
- "\nWith -cd, -hd and -c you can explicitly select the drives to be used"
- "\nfor hard disk, CD-ROM drive and concurrent hard disk and CD-ROM benchmarks.\n"
- "\nIf none of them is used, all drives are used for hard disk and CD-ROM"
- "\ndrive benchmarks and the first hard disk and CD-ROM drives are used"
- "\nfor the concurrent hard disk and CD-ROM benchmark\n"
- "\nExample: diskio -hd 2 3 -cd 1 -c 3 1\n");
- exit(1);
- }
-
- else
- nCount++;
- }
- else
- {
- for (nCount = 1; nCount <= nDisks; nCount++)
- xHD[nCount - 1] = nCount;
-
- for (nCount = 1; nCount <= nCDROMs; nCount++)
- xCD[nCount - 1] = nCount;
-
- if (nDisks > 0 && nCDROMs > 0)
- cHD = cCD = 1;
- }
-
- printf("\nDhrystone 2.1 C benchmark routines (C) 1988 Reinhold P. Weicker\n");
- bench_dhry();
-
- for (nCount = 0; nCount < nDisks; nCount++)
- bench_hd(xHD[nCount]);
-
- for (nCount = 0; nCount < nCDROMs; nCount++)
- bench_cd(xCD[nCount]);
-
- if (cHD != 0 && cCD != 0)
- bench_concurrent(cHD, cCD);
-
- return 0;
- }
-
- /* end of diskio.c */
-