1 /* Copyright (C) 2021-2023 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
26 #include <sys/types.h>
33 #include "stopwatch.h"
35 /* parameters defining various tasks */
39 #define SIZE ((int)(16*1024*1024))
40 unsigned buffer
[SIZE
];
43 /* ioerror - do some erroneous file IO operations */
47 FILE *fp
; /* FILE pointer for stdio */
50 int fd
; /* file descriptor for raw IO */
51 int fd2
; /* file descriptor for raw IO */
54 unsigned long size
= 0;
57 /* Log the regular read */
58 wlog ("start of ioerror", NULL
);
60 /* fname is set to NULL.
61 Use various calls to create
65 fd
= creat (fname
, 0666);
66 fd
= open (fname
, 0666);
68 fd
= openat (fd2
, fname
, 0666);
69 fp
= fopen (fname
, "w");
70 fp
= fopen ("/iotest", "w");
73 stat
= chmod (fname
, 755);
74 stat
= access (fname
, 755);
75 fname
= "/tmp/synprogXXXXXX";
76 strncpy (sfn
, fname
, sizeof (sfn
));
79 stat
= rename (fname
, NULL
);
81 fp
= fopen (fname
, "w");
83 stat
= fread (buf
, 100, 2, fp
);
84 stat
= fwrite (buf
, 100, 2, fp
);
85 ptr
= fgets (buf
, size
, fp
);
86 read (10000, buf
, 100);
87 write (10000, buf
, 100);
88 stat
= unlink (fname
);
90 stat
= mkdir (fname
, 755);
91 stat
= unlink (fname
);
93 These functions cannot be executed
94 if the File Pointer (fp) is set
95 to NULL. They generate segv failure
96 in actual call not inside of
99 stat = fread(buf, size, 2, fp);
100 stat = fwrite(buf, size, 2, fp);
101 ptr = fgets(buf, size, fp);
102 stat = fputs(buf, fp);
103 stat = fprintf(fp, "%d\n", size);
104 stat = fseek(fp, size, size);
108 stat = fsetpos(fp, &pos);
109 stat = fgetpos(fp, &pos);
114 /*=======================================================*/
116 /* iofile - do some file io operations */
120 FILE *fp
; /* FILE pointer for stdio */
121 int k
; /* temp value for loop */
127 char *fname
= "/tmp/synprogXXXXXX";
136 start
= gethrtime ();
137 vstart
= gethrvtime ();
140 bytes
= wlog ("start of iofile -- stdio", NULL
);
144 strncpy (sfn
, fname
, sizeof (sfn
));
149 fprintf (stderr
, "Unable to make a temporary name\n");
152 bytes
= fprintf (stderr
, "\tUsing %s as scratch file\n", sfn
);
156 /* allocate a buffer for the reading */
157 /* note that this buffer is leaked! */
158 buf
= (char *) malloc (BUFSIZE
);
161 fp
= fdopen (ret
, "w");
165 fprintf (stderr
, "++ERROR opening %s, error %d\n", sfn
, errno
);
169 /* loop, writing the buffer to the file... */
170 for (i
= 0; i
< NBLKS
; i
++)
172 k
= fwrite (buf
, sizeof (char), BUFSIZE
, fp
);
176 fprintf (stderr
, "++ERROR writing %s, error %d\n", sfn
, errno
);
186 sprintf (buf
, "fwrite: %d blocks of %d", i
, BUFSIZE
);
187 bytes
= whrvlog (gethrtime () - start
, gethrvtime () - vstart
, buf
, NULL
);
192 /* now reopen the file, and read it */
193 start
= gethrtime ();
194 vstart
= gethrvtime ();
196 fp
= fopen (sfn
, "r");
200 fprintf (stderr
, "++ERROR opening %s, error %d\n", sfn
, errno
);
206 k
= fread (buf
, sizeof (char), BUFSIZE
, fp
);
209 fprintf (stderr
, "++ERROR reading %s, error %d\n", sfn
, errno
);
221 else if (k
!= BUFSIZE
)
224 sprintf (buf
, "\tunexpecter short read %d on %s\n", k
, sfn
);
225 fprintf (stderr
, buf
);
231 /* bump the block counter */
242 sprintf (buf
, "fread: %d blocks of %d", i
, BUFSIZE
);
243 bytes
= whrvlog (gethrtime () - start
, gethrvtime () - vstart
, buf
, NULL
);
247 bWritten
+= 99; /* the number of bytes are written by the next fprintf */
252 fprintf (fid2
, "X %14d %14d %17d %15d %17d iofile\n",
253 bRead
, readCnt
, bWritten
, writeCnt
, otherIOCnt
);
257 /* iotest - do various io syscalls */
261 char *fname
= "/tmp/foobar";
262 int fd
; /* file descriptor for raw IO */
263 int fd2
; /* file descriptor for raw IO */
264 int k
; /* temp value for loop */
266 unsigned long size
= 0;
274 /* Log the regular read */
275 bytes
= wlog ("start of iotest", NULL
);
279 /* create an empty file */
280 fd
= creat (fname
, 0666);
283 /* dup the file descriptor */
291 /* now open the empty file */
292 fd
= open (fname
, O_RDONLY
);
295 /* loop, reading into the buffer */
299 k
= read (fd
, buf
, BUFSIZE
);
302 fprintf (stderr
, "++ERROR reading %s, error %d\n", fname
, errno
);
316 /* short eread = EOF */
325 bWritten
+= 99; /* the number of bytes are written by the next fprintf */
328 /* remove the file */
331 fprintf (fid2
, "X %14d %14d %17d %15d %17d iotest\n",
332 bRead
, readCnt
, bWritten
, writeCnt
, otherIOCnt
);
338 * Memory mapping routines-
340 * Allocate and deallocate memory using mmap and malloc.
342 * There is one parameter--the total number of megabytes to write,
343 * written in as many 16 megabyte files as are needed
346 unsigned char *start
= (unsigned char*) 0x80000000;
351 memorymap (int megabytes
)
361 * First, see how much time it takes to mmap all the files.
363 * Second, pull in just a few pages of information to see how much
364 * time the "How much IBM do I hold?" question would take.
366 * Next, compare updating the database shared with updating it private
367 * and then recopying the changed segments.
369 * (We could catch the pages that we have altered by mapping the
370 * entire BIS read-only and then punching holes in it via an
371 * mprotect call as we catch segfaults. This gives us a list
372 * of the pages that we need to write, at the added expense of
373 * handling lots of interrupts.)
374 * (Notice that we don't test the case where we are adding to
375 * the BIS files. This is an interesting situation as we either
376 * have to open the last page past the last write point or reopen
377 * extendable in some way. We could do that by opening /dev/zero
378 * with MAP_ANON for addresses above our current usage point.
382 stop
= start
+ 1024 * 1024 * (long long) megabytes
;
384 printf ("Creating %d random numbers\n", SIZE
);
385 for (i
= 0; i
< SIZE
; i
++)
386 buffer
[i
] = random (); // set pseudo-bis to noise
387 printf ("Done creating random numbers\n");
391 * Write a database consisting of 16 megabyte files.
392 * Each filename contains the memory address into which
393 * the file should be reloaded.
396 printf ("Writing pseudo-bis files\n");
397 unsigned char* base
= start
;
399 for (i
= 0; i
< megabytes
; i
+= 16)
402 // write data in 16MB files
404 sprintf (filename
, "bistest.%p.%d", base
, i
);
405 int fd
= open (filename
, O_CREAT
| O_TRUNC
| O_WRONLY
, 0660);
409 printf ("open of %s failed: %s\n", filename
, strerror (errno
));
412 bytes
= write (fd
, buffer
, SIZE
);
417 printf ("\twrote %d megabytes\n", i
+ 16);
418 base
+= 16 * 1024 * 1024;
420 printf ("Done writing files from %p to %p\n", start
, stop
);
424 printf ("Memory map all the files (private)\n");
425 for (i
= 0; i
< megabytes
; i
+= 16)
427 unsigned char* base
= start
;
428 base
+= i
* 1024 * 1024;
430 sprintf (filename
, "bistest.%p.%d", base
, i
);
431 int fd
= open (filename
, O_RDWR
);
434 printf ("open of %s failed: %s\n", filename
, strerror (errno
));
435 unsigned char *mp
= (unsigned char*) mmap ((char*) base
,
436 SIZE
, PROT_READ
| PROT_WRITE
,
437 MAP_PRIVATE
| MAP_FIXED
, fd
, 0);
438 if (mp
== MAP_FAILED
|| mp
!= base
)
440 printf ("mmap of %s failed: %s\n", filename
, strerror (errno
));
444 printf ("mapped %d bytes at %p\n", SIZE
, base
);
445 close (fd
); // mmap will hold the file open for us
449 printf ("Mapping done\n");
454 printf ("Access %d bytes at random\n", ranlimit
);
456 for (i
= 0; i
< ranlimit
; i
++)
458 unsigned char *where
= start
+
459 (((unsigned long) random ()) % (stop
- start
));
462 printf ("Random byte access done\n");
466 printf ("Alter %d random locations, %d bytes each (private)\n",
469 for (i
= 0; i
< ranlimit
; i
++)
471 unsigned char *where
= start
+
472 (((unsigned long) random ()) % (stop
- start
));
473 for (j
= 0; j
< ranrange
; j
++)
477 printf ("Memory alteration done\n");
481 printf ("Copy all memory back to disk\n");
483 for (i
= 0; i
< megabytes
; i
+= 16)
485 unsigned char* base
= start
;
486 base
+= i
* 1024 * 1024;
488 sprintf (filename
, "bistest2.%p.%d", base
, i
);
489 int fd
= open (filename
, O_RDWR
| O_CREAT
| O_TRUNC
, 0660);
491 if ((bytes
= write (fd
, base
, SIZE
)) == -1)
493 printf ("write of %s failed: %s\n", filename
, strerror (errno
));
502 printf ("Disk copy complete\n");
506 printf ("Unmap all segments\n");
507 for (i
= 0; i
< megabytes
; i
+= 16)
509 unsigned char* base
= start
;
510 base
+= i
* 1024 * 1024;
511 if (munmap ((char*) base
, SIZE
) == -1)
513 printf ("munmap failed: %s\n", strerror (errno
));
516 printf ("unmapped %d bytes at %p\n", SIZE
, base
);
518 printf ("Segment unmapping complete\n");
522 printf ("Remap all segments as shared\n");
523 for (i
= 0; i
< megabytes
; i
+= 16)
525 unsigned char* base
= start
;
526 base
+= i
* 1024 * 1024;
528 sprintf (filename
, "bistest.%p.%d", base
, i
);
529 int fd
= open (filename
, O_RDWR
);
531 char* mp
= mmap ((char*) base
, SIZE
, PROT_READ
| PROT_WRITE
,
532 MAP_SHARED
| MAP_FIXED
, fd
, 0);
533 if (mp
== MAP_FAILED
|| (unsigned char*) mp
!= base
)
535 printf ("re mmap of %s failed: %s\n", filename
, strerror (errno
));
538 printf ("remapped %d bytes at %p\n", SIZE
, base
);
539 close (fd
); // mmap will hold the file open for us
542 printf ("Remapping complete\n");
548 printf ("Alter %d random locations, %d bytes each (shared)\n",
550 for (i
= 0; i
< ranlimit
; i
++)
552 unsigned char* where
= start
+
553 (((unsigned long) random ()) % (stop
- start
));
554 for (j
= 0; j
< ranrange
; j
++)
557 printf ("Memory alteration done\n");
561 printf ("Unmap all segments\n");
562 for (i
= 0; i
< megabytes
; i
+= 16)
564 unsigned char *base
= start
;
565 base
+= i
* 1024 * 1024;
566 if (munmap ((char*) base
, SIZE
) == -1)
568 printf ("munmap failed: %s\n", strerror (errno
));
571 printf ("unmapped %d bytes at %p\n", SIZE
, base
);
573 printf ("Segment unmapping complete\n");
579 for (i
= 0; i
< megabytes
; i
+= 16)
581 // write data in 16MB files
583 sprintf (filename
, "bistest.%p.%d", base
, i
);
584 if (unlink (filename
) != 0)
586 printf ("unlink of %s failed: %s\n", filename
, strerror (errno
));
588 base
+= 16 * 1024 * 1024;
592 for (i
= 0; i
< megabytes
; i
+= 16)
594 unsigned char* base
= start
;
595 base
+= i
* 1024 * 1024;
597 sprintf (filename
, "bistest2.%p.%d", base
, i
);
598 if (unlink (filename
) != 0)
600 printf ("unlink of %s failed: %s\n", filename
, strerror (errno
));
604 bWritten
+= 102; /* the number of bytes are written by the next fprintf */
610 /* Record accounting record */
611 fprintf (fid2
, "X %14d %14d %17d %15d %17d memorymap\n",
612 bRead
, readCnt
, bWritten
, writeCnt
, otherIOCnt
);
613 printf ("Deleted scratch files\n");