/
DISKTHD.C
336 lines (304 loc) · 10.8 KB
/
DISKTHD.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
/*
*
* "I/O Stone" Benchmark Program
*
* Written by: Arvin Park (park@midas.ucdavis.edu) and
* Jeff Becker (becker@iris.ucdavis.edu)
* Division of Computer Science
* University of California, Davis
* Davis CA 95616
* (916) 752-5183
*
* Version C/II
* Date: 06/27/90
*
* Defines: If your version of "C" does not include an ftime()
* function or the C library time.h, define NOTIME.
* Use a stopwatch to measure elapsed wall time.
* Divide 2,000,000 by the elapsed time to get
* the correct number of iostones/second.
*
* To compile: cc -O io.c -o io
*
* Note: [1] This program should be run without other processes
* competing for system resources. Run it in the dead of
* night if you have to.
*
* [2] This program uses 5 megabytes of disk space. Make
* sure that at least this much space is available on
* your file system before you run the program.
*
* Results: If you get results from a new (machine/operating
* system/disk controller and drive) combination, please
* send them to becker@iris.ucdavis.edu. Please include
* complete information on the machine type, operating
* system, version, disk controller, and disk drives.
* Also make a note of any system modifications that
* have been performed.
*
*-------------------------------------------------------------------------
* 8/26/91 Tin Le
* Added simple Makefile.
*
* As far as I can determine from examining the code, iostone is
* meant for benchmarking file I/O and buffer cache efficiencies.
*
* It does this by creating NSETS (4) of SET_SIZE (99) files. Then
* iostone performs I/O on each file in each set. The type of I/O is
* randomly picked (r/w).
*
*--------------------------------------------------------------------------
* 7/21/93 Oddgeir Kvien, kvien@elkraft.unit.no
*
* Slightly modified to compile with Borland C++ for OS/2
*
*--------------------------------------------------------------------------
* 11/93 Jeffrey Patten 1:2410/242@fidonet.org
*
* IOStone gets chopped to pieces to adapt it as a portion of a
* multithreaded disk/cpu usage benchmark. The numbers generated
* are -NOT- comparable to those generated by the original program.
* No attempt was made to maintain portability - my programming skills
* are not yet advanced enough for that.
*
*--------------------------------------------------------------------------
*/
#define INCL_NOPMAPI
#define INCL_DOS
#include <os2.h>
#include "MDisk.h"
#include <dir.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
/* PREDEFINISJON */
int my_rand( int max );
void initfile( char *fname, long fsize, PDTV pDisk );
void readswrites( PDTV pDisk );
void EndItAll( int rc, PDTV pDisk );
VOID APIENTRY ThdDskPerf( ULONG ulTask )
{
int k;
PDTV pDisk;
pDisk = (PDTV)ulTask;
pDisk->szDir[ 6 ] = (char)( pDisk->ulTask + 0x30 );
pDisk->szDir[ 7 ] = 0;
setdisk( (int)( pDisk->szDrive[ 0 ] - 'A' ) );
mkdir( pDisk->szDir );
chdir( pDisk->szDir );
/* create test files */
DosPostEventSem( pDisk->hevReady );
/* start timing */
DosWaitEventSem( hevGo, SEM_INDEFINITE_WAIT );
/* perform string of file operations */
for( k = 0; k < ITER; k++ )
readswrites( pDisk );
/*stop timimg*/
EndItAll( 0, pDisk );
}
void init( PDTV pDisk )
{
int this_set; /*mark the file set (0..NSETS-1)*/
int bcount; /*counter to track #spacer files*/
int fcount; /*a counter to tell where to create*/
int i, j, k; /*files to flush buffer cache and*/
/*spread other files across disk*/
pDisk->bsize[ 0 ] = 256; pDisk->bfreq[ 0 ] = 128;
pDisk->bsize[ 1 ] = 512; pDisk->bfreq[ 1 ] = 64;
pDisk->bsize[ 2 ] = 1024; pDisk->bfreq[ 2 ] = 64;
pDisk->bsize[ 3 ] = 2048; pDisk->bfreq[ 3 ] = 64;
pDisk->bsize[ 4 ] = 4096; pDisk->bfreq[ 4 ] = 32; /*set file block sizes and*/
pDisk->bsize[ 5 ] = 8192; pDisk->bfreq[ 5 ] = 32; /*access frequencies*/
pDisk->bsize[ 6 ] = 16384; pDisk->bfreq[ 6 ] = 8;
pDisk->bsize[ 7 ] = 32768; pDisk->bfreq[ 7 ] = 2;
pDisk->bsize[ 8 ] = 65536; pDisk->bfreq[ 8 ] = 2;
k = 0; /*set up files*/
bcount = 0;
fcount = 0;
for( i = 0; i < NBLOCKSIZES; i++ )
{
for( j = 0; j < pDisk->bfreq[ i ]; j++ )
{
if( i < NBLOCKSIZES - 1 )
this_set = j % NSETS;
else
this_set = ( j + 2 ) % NSETS;
sprintf( pDisk->tmp, "%0d_%0d", i, j ); /*create filename*/
pDisk->files[ this_set ][ k ] = malloc( 1 + strlen( pDisk->tmp ));
if( ! pDisk->files[ this_set ][ k ] )
{
printf( "Could not allocate string for filename\n" );
EndItAll( 1, pDisk );
}
strcpy( pDisk->files[ this_set ][ k ], pDisk->tmp );
initfile( pDisk->tmp, pDisk->bsize[ i ], pDisk );
if( i < NBLOCKSIZES - 1 && this_set == NSETS - 1 )
k++;
if( bcount < NBFLUSH_FILES && fcount % 44 == 0 )
{
sprintf( pDisk->tmp, "%bf_%0d", bcount ); /*create spacer file*/
pDisk->buf_flush_files[ bcount ] = malloc( 1 + strlen( pDisk->tmp ));
if( ! pDisk->buf_flush_files[ bcount ] )
{
printf( "Could not allocate string for filename\n" );
EndItAll( 1, pDisk );
}
strcpy( pDisk->buf_flush_files[ bcount ], pDisk->tmp );
initfile( pDisk->tmp, BFLUSH_FILE_SIZE, pDisk );
bcount++;
}
fcount++;
}
}
for( i = 0; i < NBFLUSH_FILES; i++ )
{ /*read spacer files to flush buffers*/
if( ( pDisk->fd = open( pDisk->buf_flush_files[ i ], 2)) < 0 )
{
printf( "error opening buffer flush file\n" );
EndItAll( 1, pDisk );
}
lseek( pDisk->fd, 0L, 0 );
k = BFLUSH_FILE_SIZE / BUFFERSIZE;
for( j = 0; j < k; j++ )
{
if( ( pDisk->nbytes = read( pDisk->fd, pDisk->buffer, BUFFERSIZE )) < 0 )
{
printf( "Error reading buffer flush file\n" );
EndItAll( 1, pDisk );
}
}
close( pDisk->fd );
}
srand( SEED ); /*initialize random number generator*/
for( i = 0; i < NSETS; i++ )
{ /*permutation for reading/writing*/
for( j = SET_SIZE; j > 0; j-- )
{
k = my_rand( j );
strcpy( pDisk->tmp, pDisk->files[ i ][ j - 1 ] );
strcpy( pDisk->files[ i ][ j - 1 ], pDisk->files[ i ][ k ] );
strcpy( pDisk->files[ i ][ k ], pDisk->tmp );
}
}
}
int my_rand( int max )
{
return rand() % max;
}
void initfile( char *fname, long fsize, PDTV pDisk )
{ /*create a temporary file*/
FILE *fs;
int block, num_blocks;
if(( fs = fopen( fname, "w" )) == NULL )
{
printf( "init: Cannot create temporary file\n" );
EndItAll( 1, pDisk );
}
rewind( fs ); /*write initial portion of file*/
if( fsize > BUFFERSIZE )
{
num_blocks = fsize / BUFFERSIZE;
for( block = 0; block < num_blocks; block++ )
{
if( ( pDisk->nbytes = fwrite( pDisk->buffer, 1, BUFFERSIZE, fs)) < 0 )
{
printf( "init: error writing block\n" );
EndItAll( 1, pDisk );
}
}
}
else
{
if( ( pDisk->nbytes = fwrite( pDisk->buffer, 1, fsize, fs )) < 0 )
{
printf( "init: error writing block\n ");
EndItAll( 1, pDisk );
}
}
fclose( fs );
}
void readswrites( PDTV pDisk )
{
int i, j;
int xfer, num_xfer; /*to access buffer correct # times*/
long xfer_amt; /*amount to transfer to/from buffer*/
int fsize_index; /*file size index (0..8)*/
int rnum; /*rand. num to choose read or write*/
int rep1, rep2; /*indices to loop through each file*/
/*set twice, and all sets three times*/
for( rep1 = 0; rep1 < 3; rep1++ )
{ /*in order to achieve locality which*/
for( i = 0; i < NSETS; i++ )
{ /*is consistent with buffer cache data*/
for( rep2 = 0; rep2 < 2; rep2++ )
{ /*of Ousterhout et al (1985)*/
for( j = 0; j < SET_SIZE; j++ )
{
if( ( pDisk->fd = open( pDisk->files[ i ][ j ], 2)) < 0 )
{
printf( "readswrites: cannot open file\n" );
EndItAll( 1, pDisk );
}
fsize_index = *( pDisk->files[ i ][ j ] ) - '0'; /*max xfer_amt = BUFFERSIZE*/
if( pDisk->bsize[ fsize_index ] >= BUFFERSIZE )
{
num_xfer = pDisk->bsize[ fsize_index ] / BUFFERSIZE;
xfer_amt = BUFFERSIZE;
}
else
{
num_xfer = 1;
xfer_amt = pDisk->bsize[ fsize_index ];
}
rnum = my_rand( 3 );
if( rnum < 2 )
{ /*read:write = 2:1*/
lseek( pDisk->fd, 0L, 0 );
for( xfer = 0; xfer < num_xfer; xfer++ )
{
if( ( pDisk->nbytes = read( pDisk->fd, pDisk->buffer, xfer_amt)) < 0 )
{
printf( "readswrites %d: read error\n", pDisk->ulTask );
EndItAll( 1, pDisk );
}
}
}
else
{
lseek( pDisk->fd, 0L, 0 );
for( xfer = 0; xfer < num_xfer; xfer++ )
{
if( ( pDisk->nbytes = write( pDisk->fd, pDisk->buffer, xfer_amt)) < 0 )
{
printf( "readswrites %d: write error\n", pDisk->ulTask );
EndItAll( 1, pDisk );
}
}
}
close( pDisk->fd );
}
}
}
}
}
void EndItAll( int rc, PDTV pDisk )
{
pDisk->ulCount = ( CONST * ITER );
pDisk->iExitCode = rc;
DosPostEventSem( pDisk->hevDone );
DosExit( 0, rc );
}
void removefiles( PDTV pDisk )
{
int i, j, k;
/*remove files*/
for( i = 0; i < NSETS; i++ )
for( j = 0; j < SET_SIZE; j++ )
unlink( pDisk->files[ i ][ j ] );
for( k = 0; k < NBFLUSH_FILES; k++ )
unlink( pDisk->buf_flush_files[ k ] );
chdir( "\\" );
rmdir( pDisk->szDir );
}