(root)/
binutils-2.41/
gprofng/
testsuite/
gprofng.display/
synprog/
iosyn.c
       1  /* Copyright (C) 2021-2023 Free Software Foundation, Inc.
       2     Contributed by Oracle.
       3  
       4     This file is part of GNU Binutils.
       5  
       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)
       9     any later version.
      10  
      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.
      15  
      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.  */
      20  
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <string.h>
      24  #include <strings.h>
      25  #include <errno.h>
      26  #include <sys/types.h>
      27  #include <sys/stat.h>
      28  #include <fcntl.h>
      29  #include <unistd.h>
      30  #include <sys/mman.h>
      31  #include <sys/time.h>
      32  
      33  #include "stopwatch.h"
      34  
      35  /* parameters defining various tasks */
      36  #define BUFSIZE  16384
      37  #define NBLKS  1024
      38  
      39  #define SIZE ((int)(16*1024*1024))
      40  unsigned buffer[SIZE];
      41  extern FILE *fid2;
      42  
      43  /*	ioerror - do some erroneous file IO operations */
      44  int
      45  ioerror ()
      46  {
      47    FILE *fp; /* FILE pointer for stdio */
      48    char *fname = NULL;
      49    char *ptr = NULL;
      50    int fd; /* file descriptor for raw IO */
      51    int fd2; /* file descriptor for raw IO */
      52    int stat;
      53    char buf[BUFSIZE];
      54    unsigned long size = 0;
      55    char sfn[23] = "";
      56  
      57    /* Log the regular read */
      58    wlog ("start of ioerror", NULL);
      59  
      60    /* fname is set to NULL.
      61       Use various calls to create
      62       a file.
      63     */
      64  
      65    fd = creat (fname, 0666);
      66    fd = open (fname, 0666);
      67    fd2 = 0;
      68    fd = openat (fd2, fname, 0666);
      69    fp = fopen (fname, "w");
      70    fp = fopen ("/iotest", "w");
      71    fp = NULL;
      72    stat = fflush (fp);
      73    stat = chmod (fname, 755);
      74    stat = access (fname, 755);
      75    fname = "/tmp/synprogXXXXXX";
      76    strncpy (sfn, fname, sizeof (sfn));
      77    fd = mkstemp (sfn);
      78    stat = unlink (sfn);
      79    stat = rename (fname, NULL);
      80    unlink (fname);
      81    fp = fopen (fname, "w");
      82    stat = fclose (fp);
      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);
      89    fname = NULL;
      90    stat = mkdir (fname, 755);
      91    stat = unlink (fname);
      92    /* 
      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 
      97      the wrapper.
      98  
      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);
     105      rewind(fp);
     106      ftell(fp);
     107      fpos_t pos;
     108      stat = fsetpos(fp, &pos);
     109      stat = fgetpos(fp, &pos);
     110     */
     111    return 0;
     112  }
     113  
     114  /*=======================================================*/
     115  
     116  /* iofile - do some file io operations */
     117  int
     118  iofile ()
     119  {
     120    FILE *fp; /* FILE pointer for stdio */
     121    int k; /* temp value for loop */
     122    int i;
     123    char *buf;
     124    hrtime_t start;
     125    hrtime_t vstart;
     126    char sfn[23] = "";
     127    char *fname = "/tmp/synprogXXXXXX";
     128    int ret;
     129    int readCnt = 0;
     130    int bRead = 0;
     131    int writeCnt = 0;
     132    int bWritten = 0;
     133    int otherIOCnt = 0;
     134    int bytes = 0;
     135  
     136    start = gethrtime ();
     137    vstart = gethrvtime ();
     138  
     139    /* Log the event */
     140    bytes = wlog ("start of iofile -- stdio", NULL);
     141    bWritten += bytes;
     142    writeCnt++;
     143  
     144    strncpy (sfn, fname, sizeof (sfn));
     145    ret = mkstemp (sfn);
     146    otherIOCnt++;
     147    if (ret == -1)
     148      {
     149        fprintf (stderr, "Unable to make a temporary name\n");
     150        exit (1);
     151      }
     152    bytes = fprintf (stderr, "\tUsing %s as scratch file\n", sfn);
     153    bWritten += bytes;
     154    writeCnt++;
     155  
     156    /* allocate a buffer for the reading */
     157    /* note that this buffer is leaked! */
     158    buf = (char *) malloc (BUFSIZE);
     159  
     160    /* open the file */
     161    fp = fdopen (ret, "w");
     162    otherIOCnt++;
     163    if (fp == NULL)
     164      {
     165        fprintf (stderr, "++ERROR opening %s, error %d\n", sfn, errno);
     166        exit (1);
     167      }
     168  
     169    /* loop, writing the buffer to the file... */
     170    for (i = 0; i < NBLKS; i++)
     171      {
     172        k = fwrite (buf, sizeof (char), BUFSIZE, fp);
     173        writeCnt++;
     174        if (k != BUFSIZE)
     175          {
     176            fprintf (stderr, "++ERROR writing %s, error %d\n", sfn, errno);
     177            exit (1);
     178          }
     179        bWritten += k;
     180      }
     181  
     182    fclose (fp);
     183    fp = NULL;
     184    otherIOCnt++;
     185  
     186    sprintf (buf, "fwrite: %d blocks of %d", i, BUFSIZE);
     187    bytes = whrvlog (gethrtime () - start, gethrvtime () - vstart, buf, NULL);
     188    bWritten += bytes;
     189    writeCnt++;
     190  
     191  
     192    /* now reopen the file, and read it */
     193    start = gethrtime ();
     194    vstart = gethrvtime ();
     195  
     196    fp = fopen (sfn, "r");
     197    otherIOCnt++;
     198    if (fp == NULL)
     199      {
     200        fprintf (stderr, "++ERROR opening %s, error %d\n", sfn, errno);
     201        exit (1);
     202      }
     203    i = 0;
     204    for (;;)
     205      {
     206        k = fread (buf, sizeof (char), BUFSIZE, fp);
     207        readCnt++;
     208        if (k < 0)
     209          fprintf (stderr, "++ERROR reading %s, error %d\n", sfn, errno);
     210  
     211  
     212        if (k == 0)
     213          {
     214            /* close the file */
     215            fclose (fp);
     216            fp = NULL;
     217            otherIOCnt++;
     218            break;
     219  
     220          }
     221        else if (k != BUFSIZE)
     222          {
     223            /* short read */
     224            sprintf (buf, "\tunexpecter short read %d on %s\n", k, sfn);
     225            fprintf (stderr, buf);
     226            bRead += k;
     227            break;
     228          }
     229        else
     230          {
     231            /* bump the block counter */
     232            i++;
     233            bRead += k;
     234          }
     235      }
     236  
     237    if (fp != NULL)
     238      {
     239        fclose (fp);
     240        fp = NULL;
     241      }
     242    sprintf (buf, "fread: %d blocks of %d", i, BUFSIZE);
     243    bytes = whrvlog (gethrtime () - start, gethrvtime () - vstart, buf, NULL);
     244    bWritten += bytes;
     245    writeCnt++;
     246  
     247    bWritten += 99; /* the number of bytes are written by the next fprintf */
     248    writeCnt++;
     249  
     250    unlink (sfn);
     251    otherIOCnt++;
     252    fprintf (fid2, "X   %14d  %14d  %17d  %15d  %17d   iofile\n",
     253             bRead, readCnt, bWritten, writeCnt, otherIOCnt);
     254    return 0;
     255  }
     256  
     257  /*  iotest - do various io syscalls */
     258  int
     259  iotest ()
     260  {
     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 */
     265    char buf[BUFSIZE];
     266    unsigned long size = 0;
     267    int readCnt = 0;
     268    int bRead = 0;
     269    int writeCnt = 0;
     270    int bWritten = 0;
     271    int otherIOCnt = 0;
     272    int bytes = 0;
     273  
     274    /* Log the regular read */
     275    bytes = wlog ("start of iotest", NULL);
     276    bWritten += bytes;
     277    writeCnt++;
     278  
     279    /* create an empty file */
     280    fd = creat (fname, 0666);
     281    otherIOCnt++;
     282  
     283    /* dup the file descriptor */
     284    fd2 = dup (fd);
     285    otherIOCnt++;
     286    close (fd2);
     287    otherIOCnt++;
     288    close (fd);
     289    otherIOCnt++;
     290  
     291    /* now open the empty file */
     292    fd = open (fname, O_RDONLY);
     293    otherIOCnt++;
     294  
     295    /* loop, reading into the buffer */
     296    size = 0;
     297    for (;;)
     298      {
     299        k = read (fd, buf, BUFSIZE);
     300        readCnt++;
     301        if (k < 0)
     302          fprintf (stderr, "++ERROR reading %s, error %d\n", fname, errno);
     303        else
     304          {
     305            size = size + k;
     306            bRead += k;
     307          }
     308        if (k != BUFSIZE)
     309          {
     310            /* close the file */
     311            close (fd);
     312            fd = -1;
     313            otherIOCnt++;
     314            bRead += k;
     315  
     316            /* short eread = EOF */
     317            break;
     318          }
     319      }
     320    if (fd != -1)
     321      {
     322        close (fd);
     323        fd = -1;
     324      }
     325    bWritten += 99; /* the number of bytes are written by the next fprintf */
     326    writeCnt++;
     327  
     328    /* remove the file */
     329    unlink (fname);
     330    otherIOCnt++;
     331    fprintf (fid2, "X   %14d  %14d  %17d  %15d  %17d   iotest\n",
     332             bRead, readCnt, bWritten, writeCnt, otherIOCnt);
     333  
     334    return 0;
     335  }
     336  
     337  /*
     338   * Memory mapping routines-
     339   *
     340   *  Allocate and deallocate memory using mmap and malloc.
     341   *
     342   *  There is one parameter--the total number of megabytes to write,
     343   *  written in as many 16 megabyte files as are needed
     344   */
     345  
     346  unsigned char *start = (unsigned char*) 0x80000000;
     347  unsigned char *stop;
     348  int nblocks;
     349  
     350  void
     351  memorymap (int megabytes)
     352  {
     353    int readCnt = 0;
     354    int bRead = 0;
     355    int writeCnt = 0;
     356    int bWritten = 0;
     357    int otherIOCnt = 0;
     358    int bytes;
     359  
     360    /*
     361     * First, see how much time it takes to mmap all the files.
     362     *
     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.
     365     *
     366     * Next, compare updating the database shared with updating it private
     367     * and then recopying the changed segments.
     368  
     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.
     379     */
     380  
     381    int i;
     382    stop = start + 1024 * 1024 * (long long) megabytes;
     383  
     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");
     388  
     389  
     390    /*
     391     * Write a database consisting of 16 megabyte files.
     392     * Each filename contains the memory address into which
     393     * the file should be reloaded.
     394     */
     395  
     396    printf ("Writing pseudo-bis files\n");
     397    unsigned char* base = start;
     398    nblocks = 0;
     399    for (i = 0; i < megabytes; i += 16)
     400      {
     401        nblocks++;
     402        // write data in 16MB files
     403        char filename[256];
     404        sprintf (filename, "bistest.%p.%d", base, i);
     405        int fd = open (filename, O_CREAT | O_TRUNC | O_WRONLY, 0660);
     406        otherIOCnt++;
     407        if (fd == -1)
     408          {
     409            printf ("open of %s failed: %s\n", filename, strerror (errno));
     410            exit (0);
     411          }
     412        bytes = write (fd, buffer, SIZE);
     413        bWritten += bytes;
     414        writeCnt++;
     415        close (fd);
     416        otherIOCnt++;
     417        printf ("\twrote %d megabytes\n", i + 16);
     418        base += 16 * 1024 * 1024;
     419      }
     420    printf ("Done writing files from %p to %p\n", start, stop);
     421  
     422    int j;
     423  
     424    printf ("Memory map all the files (private)\n");
     425    for (i = 0; i < megabytes; i += 16)
     426      {
     427        unsigned char* base = start;
     428        base += i * 1024 * 1024;
     429        char filename[256];
     430        sprintf (filename, "bistest.%p.%d", base, i);
     431        int fd = open (filename, O_RDWR);
     432        otherIOCnt++;
     433        if (fd < 0)
     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)
     439          {
     440            printf ("mmap of %s failed: %s\n", filename, strerror (errno));
     441            exit (1);
     442          }
     443  
     444        printf ("mapped %d bytes at %p\n", SIZE, base);
     445        close (fd); // mmap will hold the file open for us
     446        otherIOCnt++;
     447      }
     448  
     449    printf ("Mapping done\n");
     450    fflush (stdout);
     451    otherIOCnt++;
     452  
     453    int ranlimit = 1000;
     454    printf ("Access %d bytes at random\n", ranlimit);
     455    int sum = 0;
     456    for (i = 0; i < ranlimit; i++)
     457      {
     458        unsigned char *where = start +
     459                (((unsigned long) random ()) % (stop - start));
     460        sum += (int) *where;
     461      }
     462    printf ("Random byte access done\n");
     463  
     464    ranlimit = 1000;
     465    int ranrange = 256;
     466    printf ("Alter %d random locations, %d bytes each (private)\n",
     467            ranlimit, ranrange);
     468  
     469    for (i = 0; i < ranlimit; i++)
     470      {
     471        unsigned char *where = start +
     472                (((unsigned long) random ()) % (stop - start));
     473        for (j = 0; j < ranrange; j++)
     474          *where++ = j;
     475      }
     476  
     477    printf ("Memory alteration done\n");
     478    fflush (stdout);
     479    otherIOCnt++;
     480  
     481    printf ("Copy all memory back to disk\n");
     482  
     483    for (i = 0; i < megabytes; i += 16)
     484      {
     485        unsigned char* base = start;
     486        base += i * 1024 * 1024;
     487        char filename[256];
     488        sprintf (filename, "bistest2.%p.%d", base, i);
     489        int fd = open (filename, O_RDWR | O_CREAT | O_TRUNC, 0660);
     490        otherIOCnt++;
     491        if ((bytes = write (fd, base, SIZE)) == -1)
     492          {
     493            printf ("write of %s failed: %s\n", filename, strerror (errno));
     494            exit (1);
     495          }
     496        bWritten += bytes;
     497        writeCnt++;
     498        close (fd);
     499        otherIOCnt++;
     500      }
     501  
     502    printf ("Disk copy complete\n");
     503    fflush (stdout);
     504    otherIOCnt++;
     505  
     506    printf ("Unmap all segments\n");
     507    for (i = 0; i < megabytes; i += 16)
     508      {
     509        unsigned char* base = start;
     510        base += i * 1024 * 1024;
     511        if (munmap ((char*) base, SIZE) == -1)
     512          {
     513            printf ("munmap failed: %s\n", strerror (errno));
     514            exit (1);
     515          }
     516        printf ("unmapped %d bytes at %p\n", SIZE, base);
     517      }
     518    printf ("Segment unmapping complete\n");
     519    fflush (stdout);
     520    otherIOCnt++;
     521  
     522    printf ("Remap all segments as shared\n");
     523    for (i = 0; i < megabytes; i += 16)
     524      {
     525        unsigned char* base = start;
     526        base += i * 1024 * 1024;
     527        char filename[256];
     528        sprintf (filename, "bistest.%p.%d", base, i);
     529        int fd = open (filename, O_RDWR);
     530        otherIOCnt++;
     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)
     534          {
     535            printf ("re mmap of %s failed: %s\n", filename, strerror (errno));
     536            exit (1);
     537          }
     538        printf ("remapped %d bytes at %p\n", SIZE, base);
     539        close (fd); // mmap will hold the file open for us
     540        otherIOCnt++;
     541      }
     542    printf ("Remapping complete\n");
     543    fflush (stdout);
     544    otherIOCnt++;
     545  
     546    ranlimit = 1000;
     547    ranrange = 256;
     548    printf ("Alter %d random locations, %d bytes each (shared)\n",
     549            ranlimit, ranrange);
     550    for (i = 0; i < ranlimit; i++)
     551      {
     552        unsigned char* where = start +
     553                (((unsigned long) random ()) % (stop - start));
     554        for (j = 0; j < ranrange; j++)
     555          *where++ = j;
     556      }
     557    printf ("Memory alteration done\n");
     558    fflush (stdout);
     559    otherIOCnt++;
     560  
     561    printf ("Unmap all segments\n");
     562    for (i = 0; i < megabytes; i += 16)
     563      {
     564        unsigned char *base = start;
     565        base += i * 1024 * 1024;
     566        if (munmap ((char*) base, SIZE) == -1)
     567          {
     568            printf ("munmap failed: %s\n", strerror (errno));
     569            exit (1);
     570          }
     571        printf ("unmapped %d bytes at %p\n", SIZE, base);
     572      }
     573    printf ("Segment unmapping complete\n");
     574    fflush (stdout);
     575    otherIOCnt++;
     576  
     577    base = start;
     578  
     579    for (i = 0; i < megabytes; i += 16)
     580      {
     581        // write data in 16MB files
     582        char filename[256];
     583        sprintf (filename, "bistest.%p.%d", base, i);
     584        if (unlink (filename) != 0)
     585          {
     586            printf ("unlink of %s failed: %s\n", filename, strerror (errno));
     587          }
     588        base += 16 * 1024 * 1024;
     589        otherIOCnt++;
     590      }
     591  
     592    for (i = 0; i < megabytes; i += 16)
     593      {
     594        unsigned char* base = start;
     595        base += i * 1024 * 1024;
     596        char filename[256];
     597        sprintf (filename, "bistest2.%p.%d", base, i);
     598        if (unlink (filename) != 0)
     599          {
     600            printf ("unlink of %s failed: %s\n", filename, strerror (errno));
     601          }
     602        otherIOCnt++;
     603      }
     604    bWritten += 102; /* the number of bytes are written by the next fprintf */
     605    writeCnt++;
     606  
     607    fflush (fid2);
     608    otherIOCnt++;
     609  
     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");
     614  }