home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Inside Multimedia 1995 July
/
IMM0795.ISO
/
share
/
os2
/
sysbench
/
src
/
pmb_disk.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-05
|
10KB
|
477 lines
/* diskio.c - disk benchmark
*
* Author: Kai Uwe Rommel <rommel@ars.muc.de>
* Created: Fri Jul 08 1994
*/
// modified 1994-08-10 by Henrik Harmsen
#define INTERVAL 8
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <string.h>
#define INCL_DOS
#define INCL_DOSDEVICES
#define INCL_DOSDEVIOCTL
#define INCL_DOSERRORS
#include <os2.h>
static int DskOpen(char *drv, int lock,
unsigned *sides, unsigned *tracks, unsigned *sectors);
static int DskClose(int handle);
static int DskRead(int handle, unsigned side, unsigned track,
unsigned sector, unsigned nsects, void *buf);
static int DskWrite(int handle, unsigned side, unsigned track,
unsigned sector, unsigned nsects, void *buf);
static int nHandle;
static unsigned nSides, nTracks, nSectors;
static char *pBuffer;
static HEV hSemTimer;
static HTIMER hTimer;
static QWORD nStart, nStop;
extern void err(char* s);
extern void warn(char* s);
extern void log(char* s);
static int start_timer(void)
{
ULONG nPost;
APIRET rc;
if ((rc = DosResetEventSem(hSemTimer, &nPost)) && rc != ERROR_ALREADY_RESET) {
log("Disk IO test : Semaphore error.");
exit(1);
}
if(DosAsyncTimer(INTERVAL * 1000, (HSEM) hSemTimer, &hTimer)) {
log("Disk IO test : Timer error.");
exit(1);
}
if (DosTmrQueryTime(&nStart)) {
log("Disk IO test : Timer error.");
exit(1);
}
nPost = 0;
return 0;
}
static int time_over(void)
{
ULONG nPost;
if (DosQueryEventSem(hSemTimer, &nPost))
err("Disk IO test:Semaphore error.\n"), 1;
return nPost;
}
static int stop_timer(int accuracy)
{
ULONG nFreq;
if (DosTmrQueryTime(&nStop))
err("Disk IO test:Timer error.");
if (DosTmrQueryFreq(&nFreq))
err("Disk IO test:Timer error.");
nFreq = (nFreq + accuracy / 2) / accuracy;
return (nStop.ulLo - nStart.ulLo) / nFreq;
}
static int bench_transfer(void)
{
int nCnt, nData = 0, nTime;
DosSleep(500);
if (start_timer())
err("disk io error: start timer error");
for (nCnt = 0; !time_over(); nCnt++)
{
if (DskRead(nHandle, nCnt % nSides, nCnt / nSides, 1, nSectors, pBuffer))
err("disk IO test error: Disk read error.");
nData += nSectors * 512;
}
if ((nTime = stop_timer(1000)) == -1)
err("disk io error: stop timer error");
// printf("%d k/sec\n", nData / nTime);
return (double)nData / ((double)nTime * 1.0e-3);
}
static double bench_latency(void)
{
int nCnt, nSector, nTime;
srand(1);
DosSleep(500);
if (start_timer())
err("disk io error: start timer error");
for (nCnt = 0; !time_over(); nCnt++)
{
nSector = (rand() * nSectors) / RAND_MAX + 1;
if (DskRead(nHandle, 0, 0, nSector, 1, pBuffer))
err("disk IO test error: Disk read error.");
}
if ((nTime = stop_timer(1000)) == -1)
err("disk io error: stop timer error");
// nTime = nTime * 10 / nCnt;
// printf("%d.%d ms\n", nTime / 10, nTime % 10);
return (double)nTime/(double)nCnt*1.0e-3;
}
static double bench_seek(double nLatency)
{
int nCnt, nTrack, nTime;
srand(1);
DosSleep(500);
if (start_timer())
err("disk io error: start timer error");
for (nCnt = 0; !time_over(); nCnt++)
{
nTrack = rand() * nTracks / RAND_MAX;
if (DskRead(nHandle, 0, nTrack, 1, 1, pBuffer))
err("disk IO test error: Disk read error.");
}
if ((nTime = stop_timer(1000)) == -1)
err("disk io error: stop timer error");
// nTime = nTime * 10 / nCnt;
return (double)nTime/(double)nCnt*1.0e-3 - nLatency;
}
static double bench_disk_avseek(int nDisk)
{
char szName[8];
double r;
sprintf(szName, "$%d:", nDisk);
if ((nHandle = DskOpen(szName, 0, &nSides, &nTracks, &nSectors)) < 0) {
log("Disk IO test error : Cannot access disk.");
exit(1);
}
if ((pBuffer = malloc(nSectors * 512)) == NULL) {
log("Disk IO test error : malloc() failed.");
exit(1);
}
r = bench_seek(bench_latency());
free(pBuffer);
DskClose(nHandle);
return r;
}
static double bench_disk_transfer(int nDisk)
{
char szName[8];
double r;
sprintf(szName, "$%d:", nDisk);
if ((nHandle = DskOpen(szName, 0, &nSides, &nTracks, &nSectors)) < 0) {
log("Disk IO test error : Cannot access disk.");
exit(1);
}
if ((pBuffer = malloc(nSectors * 512)) == NULL) {
log("Disk IO test error : malloc() failed.");
exit(1);
}
r = bench_transfer();
free(pBuffer);
DskClose(nHandle);
return r;
}
double pmb_diskio_avseek(int disknr)
{
double r;
disknr++;
DosCreateEventSem(NULL, &hSemTimer, DC_SEM_SHARED, 0);
DosSleep(500);
r = bench_disk_avseek(disknr);
DosCloseEventSem(hSemTimer);
hSemTimer = 0;
return r;
}
double pmb_diskio_transfer(int disknr)
{
double r;
disknr++;
DosCreateEventSem(NULL, &hSemTimer, DC_SEM_SHARED, 0);
DosSleep(500);
r = bench_disk_transfer(disknr);
DosCloseEventSem(hSemTimer);
hSemTimer = 0;
return r;
}
// return number of bytes on disk nDisk
int pmb_diskio_disksize(int nDisk) {
char szName[8];
nDisk++;
sprintf(szName, "$%d:", nDisk);
if ((nHandle = DskOpen(szName, 0, &nSides, &nTracks, &nSectors)) < 0) {
log("Disk IO test error : Cannot access disk.");
exit(1);
}
DskClose(nHandle);
return nSides * nTracks * nSectors * 512;
}
int pmb_diskio_nrdisks(void) {
USHORT nDisks;
int nCount;
if (DosPhysicalDisk(INFO_COUNT_PARTITIONABLE_DISKS, &nDisks, sizeof(nDisks), 0, 0)) {
log("Disk IO test error : Cannot determine number of disks.");
exit(1);
}
return nDisks;
}
#define PHYSICAL 0x1000
#define CATEGORY(x) (((x) & PHYSICAL) ? IOCTL_PHYSICALDISK : IOCTL_DISK)
#define HANDLE(x) ((x) & ~PHYSICAL)
#pragma pack(1)
typedef struct
{
BYTE bCommand;
USHORT usHead;
USHORT usCylinder;
USHORT usFirstSector;
USHORT cSectors;
struct
{
USHORT usSectorNumber;
USHORT usSectorSize;
}
TrackTable[64];
}
TRACK;
static ULONG DosDevIOCtl32(PVOID pData, ULONG cbData, PVOID pParms, ULONG cbParms,
ULONG usFunction, HFILE hDevice)
{
ULONG ulParmLengthInOut = cbParms, ulDataLengthInOut = cbData;
return DosDevIOCtl(HANDLE(hDevice), CATEGORY(hDevice), usFunction,
pParms, cbParms, &ulParmLengthInOut,
pData, cbData, &ulDataLengthInOut);
}
static int test_sector(int handle, int side, int track, int sector)
{
char buffer[1024];
TRACK trk;
trk.bCommand = 0;
trk.usHead = side;
trk.usCylinder = track;
trk.usFirstSector = 0;
trk.cSectors = 1;
trk.TrackTable[0].usSectorNumber = sector;
trk.TrackTable[0].usSectorSize = 512;
return DosDevIOCtl32(buffer, sizeof(buffer), &trk, sizeof(trk),
DSK_READTRACK, handle) == 0;
}
static int DskOpen(char *drv, int lock,
unsigned *sides, unsigned *tracks, unsigned *sectors)
{
BIOSPARAMETERBLOCK bpb;
DEVICEPARAMETERBLOCK dpb;
HFILE handle;
USHORT physical;
ULONG action;
BYTE cmd = 0;
if (isalpha(drv[0]) && drv[1] == ':' && drv[2] == 0)
{
if (DosOpen(drv, &handle, &action, 0L, FILE_NORMAL, FILE_OPEN,
OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |
OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE, 0L))
return -1;
}
else if (drv[0] == '$' && isdigit(drv[1]) && drv[2] == ':' && drv[3] == 0)
{
if (DosPhysicalDisk(INFO_GETIOCTLHANDLE, &physical, sizeof(physical),
drv + 1, strlen(drv + 1) + 1))
return -1;
handle = physical | PHYSICAL;
}
else
return -1;
if (handle & PHYSICAL)
{
if (DosDevIOCtl32(&dpb, sizeof(dpb), &cmd, sizeof(cmd),
DSK_GETDEVICEPARAMS, handle))
{
DosPhysicalDisk(INFO_FREEIOCTLHANDLE, NULL, 0, &physical, sizeof(physical));
return -1;
}
*sectors = dpb.cSectorsPerTrack;
*tracks = dpb.cCylinders;
*sides = dpb.cHeads;
}
else
{
if (DosDevIOCtl32(&bpb, sizeof(bpb), &cmd, sizeof(cmd),
DSK_GETDEVICEPARAMS, handle))
{
DosClose(handle);
return -1;
}
*sectors = bpb.usSectorsPerTrack;
*tracks = bpb.cCylinders;
*sides = bpb.cHeads;
}
if (lock && DosDevIOCtl32(0L, 0, &cmd, sizeof(cmd), DSK_LOCKDRIVE, handle))
{
if (handle & PHYSICAL)
DosPhysicalDisk(INFO_FREEIOCTLHANDLE, NULL, 0, &physical, sizeof(physical));
else
DosClose(handle);
return -1;
}
if (*sectors >= 15) /* 360k floppies ... */
if (!test_sector(handle, 0, 0, 15))
{
if (*sectors == 15)
*tracks = 40;
*sectors = 9;
}
return handle;
}
static int DskClose(int handle)
{
BYTE cmd = 0;
USHORT physical = handle & ~PHYSICAL;
DosDevIOCtl32(0L, 0, &cmd, sizeof(cmd), DSK_UNLOCKDRIVE, handle);
if (handle & PHYSICAL)
return DosPhysicalDisk(INFO_FREEIOCTLHANDLE, NULL, 0,
&physical, sizeof(physical));
else
return DosClose(handle);
}
static int DskRead(int handle, unsigned side, unsigned track,
unsigned sector, unsigned nsects, void *buf)
{
TRACK trk;
unsigned cnt;
trk.bCommand = 0;
trk.usHead = side;
trk.usCylinder = track;
trk.usFirstSector = 0;
trk.cSectors = nsects;
for (cnt = 0; cnt < nsects; cnt++)
{
trk.TrackTable[cnt].usSectorNumber = sector + cnt;
trk.TrackTable[cnt].usSectorSize = 512;
}
return DosDevIOCtl32(buf, nsects * 512, &trk, sizeof(trk),
DSK_READTRACK, handle);
}
static int DskWrite(int handle, unsigned side, unsigned track,
unsigned sector, unsigned nsects, void *buf)
{
TRACK trk;
unsigned cnt;
trk.bCommand = 0;
trk.usHead = side;
trk.usCylinder = track;
trk.usFirstSector = 0;
trk.cSectors = nsects;
for (cnt = 0; cnt < nsects; cnt++)
{
trk.TrackTable[cnt].usSectorNumber = sector + cnt;
trk.TrackTable[cnt].usSectorSize = 512;
}
return DosDevIOCtl32(buf, nsects * 512, &trk, sizeof(trk),
DSK_WRITETRACK, handle);
}